iOS知识点

QuickLook框架详细解析(四) —— QuickLook预

2021-03-22  本文已影响0人  刀客传奇

版本记录

版本号 时间
V1.0 2021.03.22 星期一

前言

QuickLook框架提供了文档的预览功能。接下来几篇我们就一起看一下这个框架。感兴趣的可以看下面几篇。
1. QuickLook框架详细解析(一) —— 基本概览(一)
2. QuickLook框架详细解析(二) —— QuickLook 预览简单示例(一)
3. QuickLook框架详细解析(三) —— QuickLook 预览简单示例(二)

开始

首先看下写作内容:

了解如何构建自己的Quick Look预览和缩略图扩展名以在iOS中显示自定义文件类型。内容来自翻译

下面就是写作环境:

Swift 5, iOS 14, Xcode 12

接着就是正文啦。

您可能会发现自己想要在应用程序中显示文件的缩略图,或者甚至想要显示文件本身的更丰富的预览。 幸运的是,QuickLook框架使您可以轻松生成缩略图并显示许多标准文件类型的预览。

虽然这对标准文件类型非常有用,但是如果您的应用程序专注于QuickLook不能涵盖的特定文件类型,该怎么办?好吧,不要害怕。借助iOS 13中引入的Quick Look previewsthumbnail extension点,您可以在自己的应用程序以及也使用QuickLook的同一设备上的任何其他应用程序中为自定义文件类型提供自定义预览和缩略图。

注意:您会看到两种形式的间距形式,都用于后端QuickLook framework(不带空格)和面向用户的Quick Look(带空格)。名称中的空格规则似乎很复杂,因此我们努力做到平衡。

在本教程中,您将学习如何:

为此,您将使用RazeThumb,该应用程序显示文件列表并在点按时显示每个文件的Quick Look预览。您将增强该应用程序,以使用QuickLook显示代表列表中每个文件的缩略图。最后,您将为您的自定义.thumb文件类型添加Quick Look preview extensionThumbnail extension,并在appFiles应用程序中看到它。

打开下载项目材料。然后在启动程序文件夹中打开RazeThumb.xcodeproj

RazeThumb是一个简单的文档浏览应用程序。它预装了各种包含缩略图的文件类型。六种格式中的五种是标准文件类型。第六种是自定义文件类型,称为.thumb文件。

构建并运行:

该应用程序显示六种不同文件类型的列表,每种文件类型均带有一个占位符文档图标。 轻按每个文件将显示QLPreviewController,它显示文件的预览。 这就是目前所做的全部,但是您将在不断改进该应用程序。


Adding Quick Look Thumbnails

您要做的第一件事就是增强RazeThumb,以使用每种文件类型的缩略图。 当前,RazeThumb为每个文件显示一个通用文档图标。 QuickLook框架为各种文件类型提供缩略图,包括图像,PDF,音频和视频。 请查看Apple的文档Apple’s documentation,以获取有关Apple支持的其他文件类型的更多详细信息。 如果QuickLook无法识别文件类型,它仍会创建某种占位符缩略图。 将缩略图添加到应用后,您将学到更多有关此的知识。

现在,是时候开始修饰RazeThumb了。

打开Document.swift并将import Foundation更改为:

import QuickLook

在文件底部,粘贴以下扩展名:

// MARK: - QLThumbnailGenerator
extension Document {
  func generateThumbnail(
    size: CGSize,
    scale: CGFloat,
    completion: @escaping (UIImage) -> Void
  ) {
    if let thumbnail = UIImage(systemName: "doc") {
      completion(thumbnail)
    }
  }
}

上面的代码是异步缩略图生成方法的占位符。 现在,它返回文档系统图标的UIImage。 稍后,您将替换为对QuickLook框架的请求以生成缩略图。

接下来,打开DocumentThumbnailView.swift并将以下代码直接粘贴到.groupBoxStyle(PlainGroupBoxStyle())下面:

.onAppear {
  document.generateThumbnail(
    size: thumbnailSize,
    scale: displayScale
  ) { uiImage in
    DispatchQueue.main.async {
      self.thumbnail = Image(uiImage: uiImage)
    }
  }
}

上面的代码等待视图出现。 然后,它要求为每个文件提供缩略图UIImageUIImage到达后,视图将使用主线程更新SwiftUI图像Image。 这是所有用户界面更新所必需的。

构建并运行:

您会看到每个文件的文档图标现在要小得多。 这是因为您没有调整图像的大小。 但是很快,QuickLook框架将为您处理大小调整。

1. Generating a Quick Look thumbnail

要从QuickLook框架中获取缩略图,您需要使用QLThumbnailGenerator创建一个QLThumbnailGenerator.Request并执行请求。 再次打开Document.swift,并用以下代码替换generateThumbnail(size:scale:completion :)的内容:

// 1
let request = QLThumbnailGenerator.Request(
  fileAt: url,
  size: size,
  scale: scale,
  representationTypes: .all)

// 2
let generator = QLThumbnailGenerator.shared
generator.generateRepresentations(for: request) { thumbnail, _, error in
  // 3
  if let thumbnail = thumbnail {
    print("\(name) thumbnail generated")
    completion(thumbnail.uiImage)
  } else if let error = error {
    print("\(name) - \(error)")
  }
}

在上面的代码中,您将执行以下操作:

构建并运行:

现在,您将看到每种文件类型的缩略图。 不幸的是,QuickLook.thumb文件一无所知,因此其缩略图为空白。

2. Searching messages printed in the Console

现在,查看“调试”区域中的消息。 每个缩略图有三种可能的表示形式,因此控制台中针对每个显示的文档有三则消息。

在“调试”区域右下角的Filter字段中,键入.html。 您会看到三则消息 —— 一则消息显示缩略图已生成,两则消息显示失败。 这是正常现象,在要求所有表示时您可以忽略这一点。 要求所有表示的好处是您将获得至少一个可以使用的代表。

现在删除.html并输入.pdf。 对于PDF文件,QuickLook生成了两个缩略图。 DocumentThumbnailView显示占位符文档图标,然后使用生成的缩略图对其进行两次更新。 使用所有表示形式的权衡是多次更新视图的额外工作。

替换.pdf并键入.thumb。 尽管QuickLook对缩略文件一无所知,但它至少为您提供了一个缩略图,尽管它是空白的。

现在,花点时间检查框架生成的不同缩略图。 文件zombiethumb.jpghumanthumb.pdfthumbsup.txt生成了文件内容的精美缩略图。 Markdown文件thumbsdown.md的缩略图以文本形式呈现,因为该框架不支持Markdown展示。

thumbsdown.html文件将一个通用的HTML图标作为其缩略图,因为框架设计者认为渲染HTML以生成实际的缩略图效果不佳。

最后,您已经发现,greenthumb.thumb缩略图是空白图像。但是不用担心;您将很快解决该问题。

生成缩略图,给自己一个很大的“竖起大拇指”。接下来做下一个事情。


Defining and Exporting a Document Type

那么,为什么.thumb文件没有缩略图?好吧,第一个问题是系统不知道如何将此文件扩展名映射到文档类型。系统使用Uniform Type Identifiers定义已知的数据格式,同时还允许您定义自己的专有格式,例如.thumb。您可以按照相同的步骤在将来的项目中实现新的文件类型。

1. Defining a Document Type

请按照以下步骤定义新的文档类型:

使用以下详细信息填写新的文档类型:

查看您的设置。 它们应符合以下显示的内容:

2. Exporting a Document Type

既然您已经告诉系统您的应用拥有.thumb文档类型,则需要将其导出,以便其他应用可以识别.thumb文件。 这是执行此操作的步骤:

仔细检查您的设置是否符合以下显示的内容:

构建并运行

在缩略图上查看greenthumb.thumb。 通过添加和导出文档类型信息,您使iOS知道了.thumb文件类型。 默认情况下,QuickLook框架会将应用程序图标(如您在主屏幕上看到的那样)用作缩略图,因为此应用程序拥有该文件类型。 因此,RazeThumb应用程序图标现在显示为系统上所有.thumb文件的缩略图。 再给自己竖起大拇指!


Quick Look Extensions

因此,现在RazeThumb使用QuickLook框架为每个文件提供缩略图,如果您一个一个地点击每个文件,您还将看到每个文件的丰富预览,直到进入greenthumb.thumb为止:

现在该看看如何利用iOS 13中引入的新扩展点来改善.thumb文件的使用体验。

1. Adding a Quick Look preview extension

Quick Look预览扩展程序使您的应用程序可以使用完全自定义的视图控制器替换上述无聊的预览。 RazeThumb不仅可以利用您的扩展名,而且使用已安装的扩展名预览.thumb文件,所有安装的其他应用程序都将受益。

要将扩展添加到项目中,请按照下列步骤操作:

RazeThumb应用程序的Sources文件夹中有两个文件,您的新扩展程序将在生成预览时使用这些文件。 您将使用ThumbFile.swift来加载Thumb文件,并使用ThumbFileViewController.swiftThumbFile的实例作为预览呈现。

为确保这些文件也包含在新创建的ThumbFilePreview target中,请按照下列步骤操作:

在项目导航器中,展开新的ThumbFilePreview组。 Xcode添加了名为PreviewViewController.swift,MainInterface.storyboardInfo.plist的文件。 这些是构成扩展名的文件。

2. Invoking a Quick Look Preview Extension

现在,要正确调用扩展程序,您需要将其与.thumb文件类型相关联。 为此,请按照以下步骤操作:

现在,系统知道何时调用您的扩展程序,您需要自定义扩展程序提供的预览。 打开PreviewViewController.swift并将其内容替换为以下内容:

import UIKit
import QuickLook

// 1
class PreviewViewController: ThumbFileViewController, QLPreviewingController {
  // 2
  enum ThumbFilePreviewError: Error {
    case unableToOpenFile(atURL: URL)
  }

  func preparePreviewOfFile(
    at url: URL,
    completionHandler handler: @escaping (Error?) -> Void
  ) {
    // 3
    guard let thumbFile = ThumbFile(from: url) else {
      handler(ThumbFilePreviewError.unableToOpenFile(atURL: url))
      return
    }

    // 4
    self.thumbFile = thumbFile

    // 5
    handler(nil)
  }
}

这是您在上面的代码中所做的事情:

最后,在再次运行该应用程序之前,打开ThumbFilePreview / MainInterface.storyboard并删除默认情况下添加的“Hello World”标签。

构建并运行,然后单击greenthumb.thumb以调用您的扩展程序:

恭喜你!由于上述工作,QuickLook框架可以加载您的扩展名并生成.thumb文件的更好预览。再给自己竖起大拇指!

3. Adding a Thumbnail Extension

现在RazeThumb可以渲染一个thumb文件了,是时候从该渲染中生成缩略图了。为此,您可以通过将缩略图扩展名添加到项目中的方式,类似于添加最后一个扩展名的方式。

QuickLook框架使用缩略图扩展名来创建自定义文件类型的缩略图,然后通过QLThumbnailGenerator将其返回到RazeThumb以及设备上的任何其他应用程序。首先,请按照以下步骤添加下一个扩展名:

Project navigator中,展开新的ThumbFileThumbnail组。Xcode已添加ThumbnailProvider.swiftInfo.plist。这些是构成扩展名的文件。

4. Invoking a Thumbnail extension

为了调用Thumbnail扩展名,您需要将此缩略图扩展名与.thumb文件类型相关联,就像使用预览扩展名一样。

ThumbFilePreview target目标一样,ThumbFileThumbnail target也将使用ThumbFile.swiftThumbFileViewController.swift。 按照之前的相同步骤,在Project navigator中选择两个快速文件,并通过在File inspector中选中相应的复选框,将其target memberships更新为包括ThumbFileThumbnail

接下来,打开ThumbnailProvider.swift并将文件内容替换为以下内容:

import UIKit
import QuickLookThumbnailing

class ThumbnailProvider: QLThumbnailProvider {
  // 1
  enum ThumbFileThumbnailError: Error {
    case unableToOpenFile(atURL: URL)
  }

  // 2
  override func provideThumbnail(
    for request: QLFileThumbnailRequest,
    _ handler: @escaping (QLThumbnailReply?, Error?) -> Void
  ) {
    // 3
    guard let thumbFile = ThumbFile(from: request.fileURL) else {
      handler(
        nil, 
        ThumbFileThumbnailError.unableToOpenFile(atURL: request.fileURL))
      return
    }

    // 4
    DispatchQueue.main.async {
      // 5
      let image = ThumbFileViewController.generateThumbnail(
        for: thumbFile,
        size: request.maximumSize)

      // 6
      let reply = QLThumbnailReply(contextSize: request.maximumSize) {
        image.draw(in: CGRect(origin: .zero, size: request.maximumSize))
        return true
      }

      // 7
      handler(reply, nil)
    }
  }
}

这里涉及一些步骤:

注意:在此示例中,您调度到主队列,因为ThumbFileViewController.generateThumbnail(for:size :)在内部使用UIGraphicsImageRenderer(需要使用主线程)。在其他情况下,您可能直接使用其他绘图API(例如CoreGraphics),则可能不需要这样做。

构建并运行。现在,您应该会看到greenthumb.thumb的缩略图,看起来像是预览的微型版本。

祝贺您两个伟大的大拇指! RazeThumb应用程序已完成。


Trying Out Your Extensions Using the Files App

现在,您已经为.thumb文件创建了预览扩展名和缩略图扩展名,其他应用程序将可以使用该文件类型。在本部分中,您可以通过向模拟器添加.thumb文件并使用Files应用程序浏览到该文件来表明扩展程序支持其他应用程序。

以下是将缩略图文件添加到模拟器的步骤:

由于您删除了RazeThumb,因此您将不会看到缩略图,并且如果打开文件,则不会看到预览。

Xcode中,构建并运行RazeThumb以将其重新安装到模拟器上。安装RazeThumb将重新建立缩略图文件和RazeThumb之间的关联。这是因为RazeThumb包括缩略图文件的预览和缩略图扩展名。

在模拟器中打开Files应用程序:

点按On My iPhone,您将看到缩略图文件的渲染缩略图。点击greenthumb.thumb,文件将呈现其预览,就像在RazeThumb应用程序中一样。多么酷啊?


Attaching the Debugger to Your Extension

Quick Look预览扩展和缩略图扩展过程与主应用程序分开运行。它们一起安装时,它们是完全隔离的,这使系统可以在Quick Look框架中有效地使用它们,以在设备上安装的其他应用程序中生成预览和缩略图。

在开发扩展程序时,您可能需要设置一个断点并查看其执行过程,但是由于Xcode调试器只能附加到一个进程一次,因此必须决定是否将调试器附加到您的应用程序或者扩展中。

注意:在撰写本文时,在扩展中设置断点时,Xcode调试器似乎无法正常工作。一些断点似乎会导致运行循环run loop崩溃。其他时候,调试器似乎失去了与扩展的连接。您可能必须尝试几次此练习。

首先在ThumbnailProvider.swift文件中,在ProvideThumbnail(for:_ :)的开头guard let thumbFile = ThumbFile(from: request.fileURL)语句处设置一个断点。

如果您构建并运行RazeThumb并滚动直到greenthumb.thumb可见,您会注意到调试器不会在断点处停止。 不要惊慌。 您可以解决该问题。

单击scheme selector中的RazeThumb以查看带有可用schemes列表的下拉列表。 选择ThumbFileThumbnail作为scheme,然后单击Run。 当提示您选择要启动的应用程序时,选择RazeThumb并滚动直到greenthumb.thumb可见。 这次,调试器应在断点处停止。

为了获得更多乐趣,请重新运行ThumbFileThumbnail scheme,而不是选择Files应用程序以查看您的代码在其他应用程序中运行!

您现在已经了解了如何为受支持的文件类型和自定义文件类型创建Quick Look缩略图和预览。

以下是您在此过程中涉及的一些关键点:

如果您想了解更多信息,可以探索许多相关主题:

后记

本篇主要讲述了QuickLook预览和缩略图扩展的实现,感兴趣的给个赞或者关注~~~

上一篇 下一篇

猜你喜欢

热点阅读