首页 文章详情

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

知识小集 | 299 2021-10-11 15:33 0 0 0
UniSMS (合一短信)

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

事情的起因是有用户使用 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)

实现还是很容易的。

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


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter