QuickLook框架详细解析(二) —— QuickLook 预览简单示例(一)

版本记录

版本号 时间
V1.0 2020.07.09 星期四

前言

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

开始

首先看下主要内容:

在此QuickLook预览教程中,您将学习如何将常用的文件预览和编辑功能集成到iOS应用中。本文内容来自翻译

接着看一下写作环境:

Swift 5, iOS 13, Xcode 11

下面就是正文了

QuickLook是一个iOS,macOSiPadOS框架,用于展示文档,而无需处理文件。 它使用户可以预览常用的文件类型,例如PDF,TXT等。

iOS 4以来,QuickLook诞生了。许多Apple的第一方应用程序(例如Mail,Notes,FilesMessage)已经使用QuickLook。 这是显示文件预览并为用户提供基本交互的一种快速简便的方法。

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

  • 使用QLPreviewController显示文件预览。
  • 使您的数据模型类符合QLPreviewItem,使其可用于预览。
  • 使用QuickLookThumbnailing框架生成文件缩略图。
  • 使用平滑的缩放过渡动画呈现QuickLook预览。

此外,您还将学习如何让用户对PDF,图像和视频进行简单的编辑。 您准备好学习QuickLook的魔力了吗?

在启动文件夹中打开项目SpellLook.xcodeproj

该应用程序(适当命名为SpellLook)是有关学习的全部内容。在Project navigator中查看该项目的文件。

该项目包含以下关键文件和文件夹:

  • Resources:一个包含许多拼写文件的文件夹,每个拼写文件以不同的类型编写,例如PDF,DOCX,HTML,TXTZIP
  • File.swift:应用程序使用的拼写文件的类表示。
  • ViewController.swift:应用程序的主视图,其中显示带有UICollectionView的拼写教程的集合。
  • FileCell.swift:一个UICollectionViewCell,它在集合视图上显示一个文件。
  • Main.storyboard:应用程序的主故事板。

在Xcode中构建并运行您的项目。 您会看到一组拼写教程,每个都对应资源文件夹中的一个文件。

现在,当您点击任何一个spell时,什么也不会发生。因此,您无法预览任何内容。

但是,很快您将使用QuickLook开始预览魔术。在开始疯狂之前,快速浏览一下QuickLook框架所提供的功能。


Understanding the QuickLook Framework

QuickLook是一个框架,可帮助解决许多开发人员面临的常见挑战:向用户显示文件。

在预览文件时,QuickLook是一个不错的首选。它具有每个用户期望的几个常用功能,例如捏缩放,音频播放和PDF页面。您甚至可以让用户在图像和PDF上添加标记,以及简单的视频编辑。

以下是一些受支持的文件类型:

  • 图片
  • 音频和视频文件
  • PDF文件
  • HTML文件
  • iWorkMicrosoft Office文档
  • ZIP文件
  • 使用USDZ文件格式的增强现实对象,仅限iOSiPadOS

有很多受支持的类型。更好的是,QuickLook还允许您为自己的自定义类型提供自定义预览。多么酷啊?


Working with QuickLook Scenarios

需要快速显示文件预览时,请使用QuickLook。该框架消除了处理文件以及实现每种类型的功能和视图的麻烦。它可让您专注于应用程序中的重要事项,同时提供出色的灵活性和功能。

QuickLook为用户提供了他们已经期望的许多其他第一方iOS应用程序所带来的体验。例如,在预览图像集合时,用户可以左右滑动以浏览图像。

QuickLook带有内置手势,例如捏到缩放,滑动以关闭和滚动PDF页面。您可以免费获得这些简单的互动!

该框架显示预览并提供对常用文件的简单编辑支持。但是,它不支持更多高级功能和复杂的视图层次结构。在这种情况下,您可能想探索其他方法,例如建立自己的视图。

由于SpellLook的目标是让用户学习用许多不同文件类型编写的spells,因此QuickLook非常适合。


Previewing Files With QLPreviewController

要预览文件,您将使用一种称为QLPreviewController的专用视图控制器类型。在ViewController.swift中,通过在文件顶部添加以下行来导入QuickLook

import QuickLook

然后,在collectionView(_:didSelectItemAt :)的末尾添加以下代码:

// 1
let quickLookViewController = QLPreviewController()
// 2
quickLookViewController.dataSource = self
// 3
quickLookViewController.currentPreviewItemIndex = indexPath.row
// 4
present(quickLookViewController, animated: true)

上面的代码:

  • 1) 实例化QLPreviewController的实例,该实例可以显示常见文件类型的预览。
  • 2) 将数据源属性设置为selfQLPreviewController使用您从UIKit中已经知道的经典数据源模式向控制器提供项目。 数据源的工作方式与UITableViewDatasourceUICollectionViewDataSource相似。
  • 3) 将当前预览索引设置为所选索引路径的行。 预览多个文件时,需要在控制器上设置当前预览文件的索引。
  • 4) 与其他任何警报或视图控制器一样,呈现QLPreviewController实例。

Xcode识别到ViewController并未为QLPreviewController实现数据源,因此无法将其设置为self。 要解决此问题,请在ViewController的底部添加以下扩展名:

// MARK: - QLPreviewControllerDataSource
extension ViewController: QLPreviewControllerDataSource {
  func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
    files.count
  }

  func previewController(
    _ controller: QLPreviewController,
    previewItemAt index: Int
  ) -> QLPreviewItem {
    files[index].url as NSURL
  }
}

QLPreviewControllerDataSource要求您实现两个方法,numberOfPreviewItems(in :)PreviewController(_:previewItemAt :)。 这些协议为控制器提供了要预览的项目以及需要在预览列表中包含多少个项目。

这些协议提取的文件由默认的FileManager加载。 您可以在File.swift中找到该代码。

构建并运行。 选择Light CharmQuickLook将打开一个预览该文件的视图。

注意:您可能会在调试控制台中看到许多“自动布局”消息。 这些都是来自Apple的代码,可以安全地忽略。

预览许多文件时,QLPreviewController在预览的右下角添加一个列表按钮图标以打开导航列表。 在这里,您会看到控制器当前正在预览的项目列表。 您甚至可以左右滑动以浏览文件。

QuickLook还提供了一个用于打开默认共享表的按钮。 您可以将文件保存在Files应用中,甚至可以与朋友共享。 另外,如果PDF页面与屏幕不符,您可以放大缩放并滚动它。

您也可以使用QuickLook预览ZIP文件中的文件,即使这些文件受密码保护也是如此。 使用少量的代码,您可以预览各种文件。

QuickLook是不是很神奇? PS:密码是秘密。 小心不要走到黑暗的一面。


Conforming to QLPreviewItem

您可能已经注意到PreviewController(_:previewItemAt :)要求您返回QLPreviewItemQLPreviewController使用此协议作为文件的抽象。 使您的数据模型与之保持一致,可使QLPreviewController预览它们。

该协议定义了两个必需的属性:previewItemURLpreviewItemTitle。 第一个是磁盘上的URL,即文件所在的位置,第二个是QLPreviewController在项目导航列表中使用的标题。

打开File.swift并通过在文件顶部添加以下行来导入QuickLook

import QuickLook

然后,在文件末尾添加如下代码:

// MARK: - QLPreviewItem
extension File: QLPreviewItem {
  var previewItemURL: URL? {
    url
  }
}

通过将此类遵循QLPreviewItem,可以将File的实例返回到委托方法。 如果您没有将值返回给PreviewItemTitle,则QLPreviewController使用URL的最后一个路径部分作为标题。

注意:NSURL已经符合QLPreviewItem。 如果您没有文件的类表示形式,则可以使用NSURL的实例作为QLPreviewItem

返回到ViewController.swift并将PreviewController(_:previewItemAt :)中的代码替换为:

files[index]

构建并运行。 打开一个spell以确保一切正常。

该应用程序将继续按预期方式打开教程,但是现在您要做的就是为所选索引返回File的实例。


Generating Thumbnails for Each Document

到目前为止,该应用程序看起来还不错,但是如果您可以看到要预览的文档的缩略图,那就更好了。 幸运的是,使用QuickLookThumbnailing框架可以轻松生成缩略图。

打开File.swift并将此代码添加到QLPreviewItem类扩展下面:

// MARK: - QuickLookThumbnailing
extension File {
  func generateThumbnail(completion: @escaping (UIImage) -> Void) {
    // 1
    let size = CGSize(width: 128, height: 102)
    let scale = UIScreen.main.scale
    // 2
    let request = QLThumbnailGenerator.Request(
      fileAt: url,
      size: size,
      scale: scale,
      representationTypes: .all)
    
    // 3
    let generator = QLThumbnailGenerator.shared
    generator.generateBestRepresentation(for: request) { thumbnail, error in
      if let thumbnail = thumbnail {
        completion(thumbnail.uiImage)
      } else if let error = error {
        // Handle error
        print(error)
      }
    }
  }
}

以下是发生的情况的细分:

  • 1) 您定义大小和比例。 框架使用它们来生成该大小和比例的缩略图。
  • 2) 然后,您可以使用文件的URL,大小,比例和表示形式创建缩略图请求。
  • 3) 最后,您使用QLThumbnailGenerator生成该请求的缩略图。 通过调用generateBestRepresentation(for:completion :),框架可以为文件生成最佳的缩略图表示形式,或者返回错误。

打开FileCell.swift并在update(with:)末尾添加以下内容:

file.generateThumbnail { [weak self] image in
  DispatchQueue.main.async {
    self?.thumbnailImageView.image = image
  }
}

加载集合视图时,这将更新主线程上的缩略图。 生成并运行以查看结果。

使cell出队时,文件会生成一个缩略图,并将其分配给cellUIImageView。 现在,您甚至可以在打开文件之前查看正在预览的内容。 当QuickLook无法生成缩略图时,它将生成该类型的图标表示。

为大文件生成高质量缩略图时,QLThumbnailGenerator可能需要一些时间。 幸运的是,还有另一种方法可以解决此问题:generateRepresentations(request:update :)

打开File.swift。 在generateThumbnail(completion :)内部,替换:

generator.generateBestRepresentation(for: request) { thumbnail, error in

使用下面的

generator.generateRepresentations(for: request) { thumbnail, _, error in

此方法快速生成文件图标或低质量的缩略图,然后调用updateHandler。 一旦有更高质量的缩略图可用,框架将再次调用updateHandler。 如果此缩略图在下一个缩略图之前可用,则它可能会完全跳过第一个调用。

进行构建并运行以确保一切正常。


Adding the Default Zoom Transition

动画是iOS用户界面的重要组成部分。 它们给您的应用程序带来了优美的感觉和连续性。 在iOS 10中引入了QuickLook,它提供了一种简便的方法来添加动画,而这种现代方法可以为您完成所有繁重的工作。

打开ViewController.swift并在类顶部添加一个新属性:

weak var tappedCell: FileCell?

然后,在collectionView(_:didSelectItemAt :)内部,在quickLookViewController.dataSource = self下添加以下内容:

tappedCell = collectionView.cellForItem(at: indexPath) as? FileCell
quickLookViewController.delegate = self

此代码存储被点击的cell并将委托属性设置为self。 但是,由于ViewController不符合QLPreviewControllerDelegate,因此无法将self设置为委托。 要解决此问题,请在文件底部创建一个符合QLPreviewControllerDelegate的类扩展:

// MARK: - QLPreviewControllerDelegate
extension ViewController: QLPreviewControllerDelegate {
  func previewController(
    _ controller: QLPreviewController,
    transitionViewFor item: QLPreviewItem
  ) -> UIView? {
    tappedCell?.thumbnailImageView
  }
}

通过将任何UIView返回给PreviewController(_:transitionViewFor :),框架将创建从该视图到预览的平滑缩放过渡。 在这里,您返回被点击的单元格的UIImageView来创建此过渡。

在显示或关闭预览时,QuickLook使用单元格缩略图创建平滑的缩放过渡。

构建并运行。 选择一个spell以查看进行中的过渡。


QuickLook Editing Tools

iOS 13为用户带来了一个很酷的新功能:通过QuickLook对图像,PDF和视频进行简单的编辑支持。 这使用户可以从QLPreviewController预览和编辑文件。 这些工具与在Files中预览文件或在Mail中编辑附件时使用的工具相同。

QLPreviewController还为修剪和旋转视频提供了简单的支持。 例如,当您需要在PDF教程上做一些笔记时,这非常方便。

注意:捆绑文件是只读的,这意味着除非将副本与所做的修改一起保存在其他地方,否则您将无法对其进行编辑。 为简单起见,该应用程序在首次启动时会将每个文件复制到其documents文件夹中。 该应用使用这些副本显示spells的集合。

1. Enabling PDF Editing

ViewController.swift中,将以下代码添加到文件底部的QLPreviewControllerDelegate扩展中:

func previewController(
  _ controller: QLPreviewController,
  editingModeFor previewItem: QLPreviewItem
) -> QLPreviewItemEditingMode {
  .updateContents
}

您在此处返回一个值,该值指示预览控制器如何编辑文件内容。 QuickLook通过覆盖原始文件.updateContent或通过创建其编辑副本.createCopy来处理编辑。 如果您不希望用户编辑该文件,则可以返回.disabled,而QuickLook不会显示编辑按钮。

构建并运行。 选择Light Charm教程,然后点击右上角的新编辑按钮。 当出现标记面板时,用您喜欢的颜色突出显示其说明。

QuickLook将所做的更改保存在原始文件中,但是您可能会注意到这些更改没有反映在缩略图上。 那是因为您必须使用编辑后的文件为该文件生成新的缩略图。

要解决此问题,请在QuickLook保存更改后更新UI。 将此代码添加到QLPreviewControllerDelegate扩展块内:

func previewController(
  _ controller: QLPreviewController,
  didUpdateContentsOf previewItem: QLPreviewItem
) {
  guard let file = previewItem as? File else { return }
  DispatchQueue.main.async {
    self.tappedCell?.update(with: file)
  }
}

预览控制器覆盖原始文件的内容后,QLPreviewController调用PreviewController(_:editUpdateContentsOf :)。 您可以通过重新加载该单元格的内容来更新UI。

为已编辑文件创建副本时,QLPreviewController在保存时会调用另一种方法PreviewController(_:didSaveEditedCopyOf:at :)。 在这里,框架为您提供了一个临时URL,其中是编辑后的文件。 您可以使用此URL将文件保存在应用程序文件夹中的任何位置。

构建并再次运行。 在文件上进行另一个编辑。 保存时,单元格将更新为新的缩略图。

很好! 本教程到此结束。

在本教程中,您学习了如何使用QuickLook预览常用文件,生成缩略图,甚至启用简单的PDF编辑。 但是您可以在该主题上学习更多。 例如,您可以使用Preview扩展名为自定义文件类型提供自定义预览,甚至可以使用“快速查看”缩略图扩展名为自定义文件格式提供自定义缩略图。

要了解有关Quick Look的更多信息,请从头开始的会话中查看WWDC 2018Quick look Previews from the ground upWWDC 2019What’s New in File Management and Quick Look

后记

本篇主要讲述了QuickLook预览简单示例,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353