Tip #002:聊聊把微信拱上微博热搜的那个 API

758次阅读  |  发布于3年以前

最近,微信又上微博热搜了。

事情的起因是有用户使用 iOS 15 的“记录App活动”新特性,对手机的隐私读取行为进行了监控,并使用 App Privacy Insights 应用分析了数据,进而发现微信在用户未主动激活应用的情况下,在后台有读取用户相册的行为。然后微信就这么被送上了热搜。

当然,微信官方也给出了回应,称iOS系统为 App 开发者提供相册更新通知标准能力,相册发生内容更新时会通知到 App,提醒 App 可以提前做准备,App 的该准备行为会被记录成读取系统相册。

也就是我们在聊天时,可以借助这一功能来快捷发图。

我们这个技术小 Tip 就不讨论这种大事,而是来看看技术实现。

从行为上看微信是在监听相册的内容更新,所以这应该是用到了 PhotoKit 库中的 PHChange 这个类,该对象可以通知应用程序相册的变更。应用程序可以实现 PHPhotoLibraryChangeObserver 协议并使用 PHPhotoLibrary 对象注册您的观察者。注册观察者对象后,就可以实时接收相册变更的消息。

PHPhotoLibraryChangeObserver 协议只有一个方法

func photoLibraryDidChange(PHChange)

以下是官方文档给出的示例

func photoLibraryDidChange(_ changeInstance: PHChange) {
    guard let collectionView = self.collectionView else { return }
    // Change notifications may be made on a background queue.
    // Re-dispatch to the main queue to update the UI.
    DispatchQueue.main.sync {
        // Check for changes to the displayed album itself
        // (its existence and metadata, not its member assets).
        if let albumChanges = changeInstance.changeDetails(for: assetCollection) {
            // Fetch the new album and update the UI accordingly.
            assetCollection = albumChanges.objectAfterChanges! as! PHAssetCollection
            navigationController?.navigationItem.title = assetCollection.localizedTitle
        }
        // Check for changes to the list of assets (insertions, deletions, moves, or updates).
        if let changes = changeInstance.changeDetails(for: fetchResult) {
            // Keep the new fetch result for future use.
            fetchResult = changes.fetchResultAfterChanges
            if changes.hasIncrementalChanges {
                // If there are incremental diffs, animate them in the collection view.
                collectionView.performBatchUpdates({
                    // For indexes to make sense, updates must be in this order:
                    // delete, insert, reload, move
                    if let removed = changes.removedIndexes where removed.count > 0 {
                        collectionView.deleteItems(at: removed.map { IndexPath(item: $0, section:0) })
                    }
                    if let inserted = changes.insertedIndexes where inserted.count > 0 {
                        collectionView.insertItems(at: inserted.map { IndexPath(item: $0, section:0) })
                    }
                    if let changed = changes.changedIndexes where changed.count > 0 {
                        collectionView.reloadItems(at: changed.map { IndexPath(item: $0, section:0) })
                    }
                    changes.enumerateMoves { fromIndex, toIndex in
                        collectionView.moveItem(at: IndexPath(item: fromIndex, section: 0),
                                                to: IndexPath(item: toIndex, section: 0))
                    }
                })
            } else {
                // Reload the collection view if incremental diffs are not available.
                collectionView.reloadData()
            }
        }
    }
}

然后需要用 PHPhotoLibrary 共享单例来注册对象

PHPhotoLibrary.shared().register(self)

实现还是很容易的。

另说一句,经此事件后,对相册权限的访问也许会迎来一波整改,毕竟这属于用户隐私数据,在监管的范围之内,各位开发者做好准备咯。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8