大多数浏览器和
Developer App 均支持流媒体播放。
-
探索 PhotoKit 的变更记录
PhotoKit 可以帮助您构建丰富的以照片为中心的功能。了解如何借助 PhotoKit 中的最新 API 轻松追踪对图片素材的变更。我们将介绍 PHPhotoLibrary 变更记录 API 并演示如何在每次启动时保留变更令牌,以帮助您的 App 识别用户照片图库新增和删除的内容,以及对照片图库的更新。要进一步了解照片图库集成,请务必观看 WWDC22 的“照片挑选器的新增内容”和 WWDC21 的“优化 App 中的照片访问”。
资源
相关视频
WWDC23
WWDC22
WWDC21
-
下载
♪ 柔和乐器演奏的嘻哈音乐 ♪ ♪ 您好我叫 Mindy 我是相册团队的工程师 今天我将介绍 如何在您的 App 中 获得图片变更的历史记录 PhotoKit 提供了一组 丰富的 API 用于对照片库中的照片、视频和相册 进行访问和更新 PhotoKit 是专为需要深层 访问和集成相册 的 App 而设计的 用于管理、编辑照片或自定义相机 或构建让人们以独特的方式 浏览照片库的 App 这些类型的 App 可能需要监控 照片库随时间变化情况 以便于更加密切的反映相册的内容 假设我创建了一个社交远足 App 允许人们分享和编辑 和朋友一起远足旅行的照片 当有人启动 App 时 该 App 通过 获取从旅行开始到结束的时间戳 收集最近一次远足时的手机照片 并把他们在山上远足经历 的生成拼贴画 拼贴画与图片库中所选照片 保持同步 如果有人收到远足照片 例如来自朋友的 该 App 将使用 这些更新照片生成新的拼贴画 到目前为止为了让 App 发现 新插入的图片资产 并对以前的远足拼贴画进行更改 该 App 需要 执行一系列参数提取 要确定插入了哪些图片资产 该 App 需要能够获取 图片资产创建日期 晚于 App 最后一次启动日期的资产 确定资产更新和删除的日期比较棘手 该 App 需要重新获取 每个拼贴中的每个图片资产 并检查图片修改日期 从而确定图片资产的更新时间 但这可能会带来误报 作为图片资产 图片的修改时间 可以由相册的内部处理活动设置 照片库中的删除更难追踪 因为需要提取所有跟踪的资产 并对未随提取返回的资产进行区分 总的来说这意味着每次启动 App 都需要做三个单独的检查 如果 App 显示大量图片资产 那么提取和计算开销会非常大 而不是对不确定的结果 进行不同的提取和检查 如果有办法把确已发生的图片变化 统一到一个 API 调用里会怎么样呢? 好吧 我很高兴地告诉您我们已经做到了! 新的变更历史 API 允许以更简单的方式 跟踪照片库的离线更新 变更历史由变更时间线组成 例如插入、更新 和删除照片库 在这个时间线示例中 过去三天 有各种资产、相簿和文件夹的更改 保存于变更历史记录中 使用此时间线您如何确定 最近两天发生了哪些变化 或者上一次您启动 App 的时间? 您现在可以使用持久化更改令牌 在给定的时间点 表示照片库的状态 此令牌可以 在 App 启动时持久化 并且它可用于获取该令牌生成后 照片库的更改 包括第三方 App 的修改 请注意如果您的应用处于受限库模式 则只有更改 用户选择的 PhotoKit 对象 会返回信息 此更改令牌是设备本地的 并且任何时候从 持久化更改或图片库实例访问 开销都会更小 这个新的 API 在以下任何平台上都可用 支持 PhotoKit 的平台有 macOS、iOS、iPadOS 和 tvOS 当您的 App 正在运行并使用照片库时 您可以在 App 中 存储持久化更改令牌 您可以使用该令牌来获取此后 发生的照片库更改 对于每一个持久化更改 您可以对于三种类型的相册对象 获取更改详细信息 资产、资产集合和集合列表 那么这在代码中是什么样的呢? 首先 您需要使用 上次存储的更改令牌 获取持久化更改 接下来您需要枚举 并获取更改对象更改详细信息—— 在本例中 每个持久化更改对象 都是“asset”型 这些更改详细信息提供了 自更改令牌以来 更新、删除 和插入到照片库中的 本地标识符的信息 处理完这些改动后 您可以存储最后一个更改令牌 以供将来使用 让我们对比一下 新的持久化历史 API 和现有的改变观察者 API PHChanges 处理活动的 内存中的获取结果 并在您的 App 运行时 用于记录照片库的实时更改 另一方面 持久化历史记录 记录了对照片库的长期更改 并可用于报告 App 不活动时的更改 您可以根据您的 App 的需求 同时使用这两种 API 或者任选其一 回到远足应用示例 我现在想使用持久化历史 API 跟踪资产变化 以便于创建和更新远足拼贴画 首先我将使用最后存储的更改令牌 并获取持久化更改 接下来我将遍历持久化更改 抓取相关资产的变更明细 然后进行插入、更新操作 并删除标识符 现在我需要从变更历史中 识别出影响 App 的图片库更改 因为 App 不需要获取 更改返回的所有信息 对 App 来说 了解哪一个远足图片资产 已加入到图片库 以及哪些被更新和删除的资产 在以前的远足拼贴画中引用过很重要 我已经通过持久化更改 生成了三个枚举定义 插入、更新和删除资产的 本地标识符 我现在如何更新 App 以反映这些状态? 使用插入标识符集 我可以通过获取 每次远足的开始和结束日期 通过远足图片资产的插入时间戳 和他们的创建时间 来确定添加了哪些资产 更新后的资产可能会进行调整 所以我可以使用新的 hasAdjustments API 检查我是否需要 在 UI 中重绘资产 我可以使用已删除资产的本地标识符 以确定哪些拼贴画需要重新生成 现在我已经处理了 所有离线照片库的更改 并且我的 App 的内容是最新的 以下是当您使用 新的变更历史 API 时 应该记住的几件事 首先确定哪些更改对您 和您的 App 很重要 并且只检查这些更改 考虑执行一个 更新和插入资产的大型获取请求 以提高性能 而不是用多个较小的请求 照片库的内容可能会因处理 和后台同步活动而发生很大变化 所以您最终可能会在 大量变化中进行枚举 尤其是当您的 App 不经常启动 正因为如此我们推荐您 在后台线程上请求更改历史记录 以避免阻塞 UI 在获取持久化历史记录时 可能发生两种类型的错误 如果更改令牌 比更改的可用历史记录更早 将返回更改令牌过期的报错 在某些情况下持久化更改 不能依赖于完全重建 所发生的更改 并将返回更改详细信息不可用的报错 在这些情况下我们建议 重新获取照片库中的跟踪对象 以确保您的应用的内容是最新的 在我们结束之前 还有一些我想与您分享 新的 PhotoKit API 的内容 PhotoKit 现在 支持按媒体子类型 和智能相册访问电影视频 还有两个新的错误代码 如果照片库绑定 在 macOS 系统的 File Provider 同步根目录下 图片库可能会损坏 尝试执行更改时将返回错误 如果由于网络问题 找不到资产资源 资源请求将返回网络错误的报错 请在开发者文档查看 所有最新的更新 最后一定要在相册选取器中 看看今年的会议 因为它是使用和访问 相册的最简单方法 我们很高兴您能 使用新的变更历史 API 以及 PhotoKit 中 所有出色的新功能 谢谢! ♪
-
-
0:01 - Tracking photo library changes
// Discover added assets let options = PHFetchOptions() options.predicate = NSPredicate(format: "creationDate > %@", lastLaunchDate as CVarArg) let insertedAssets = PHAsset.fetchAssets(with: options)
-
0:02 - Tracking photo library changes (2)
let fetchResult = PHAsset.fetchAssets(with: localIdentifiers, options: nil) // Discover all modified and deleted assets fetchResult.enumerateObjects { asset, idx, stop in if asset.modificationDate?.compare(lastLaunchDate) == .orderedDescending { // Asset could have been modified } if !localIdentifiers.contains(asset.localIdentifier) { // Asset could have been deleted } }
-
0:03 - Fetching persistent changes using persistent change token
let persistentChanges = try! PHPhotoLibrary.shared().fetchPersistentChanges(since: self.lastStoredToken) for persistentChange in persistentChanges { if let changeDetails = persistentChange.changeDetails(for: PHObjectType.asset) { let updatedIdentifiers = changeDetails.updatedLocalIdentifiers let deletedIdentifiers = changeDetails.deletedLocalIdentifiers let insertedIdentifiers = changeDetails.insertedLocalIdentifiers } } // After processing change details self.lastStoredToken = lastPersistentChange.changeToken
-
0:04 - Identifying important changes
// Get last stored change token let changeToken = self.lastStoredToken // Fetch persistent changes let persistentChanges = try! library.fetchPersistentChanges(since: changeToken) for persistentChange in persistentChanges { // Grab change details and process updates }
-
0:05 - Using inserted identifiers
let insertedAssets = PHAsset.fetchAssets(with: insertedIdentifiers, options: nil) insertedAssets.enumerateObjects { asset, idx, stop in for hike in hikes { let dateInterval = NSDateInterval(start: hike.startDate, end: hike.endDate) if dateInterval.contains(asset.creationDate) { // This hike contains a new added asset } } }
-
0:06 - Using updated identifiers
let updatedAssets = PHAsset.fetchAssets(with: updatedIdentifiers, options: nil) updatedAssets.enumerateObjects { asset, idx, stop in if asset.hasAdjustments { // This asset has edits } }
-
0:07 - Using deleted identifiers
for deletedIdentifier in deletedIdentifiers { for collage in collages { if collage.assetLocalIdentifiers.contains(deletedIdentifier) { // This collage needs to be redrawn } } }
-
0:08 - Handling errors
do { let persistentChanges = try library.fetchPersistentChanges(since: changeToken) } catch PHPhotosError.persistentChangeTokenExpired, PHPhotosError.persistentChangeDetailsUnavailable { let fetchResult = PHAsset.fetchAssets(with: trackedIdentifiers, options: options) // Use fetch result }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。