【问题标题】:detect deleted image from photo gallery in swift快速检测从照片库中删除的图像
【发布时间】:2018-12-10 17:22:33
【问题描述】:

我正在保存照片库图像的 PHAsset 的本地标识符并显示这些 集合视图中的图像。我的问题是当我从照片库中删除图像时 然后我的应用程序崩溃,因为它无法获取已删除的 PHAsset 从照片库。这是我显示资产的代码:

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = photoCollectionView.dequeueReusableCell(withReuseIdentifier: "imageShowCell", for: indexPath) as! imageShowCell
     let image = photoArray.object(at: indexPath.item) as! Photos
     let imageManager = PHImageManager()
     let asset = PHAsset.fetchAssets(withLocalIdentifiers: [image.pic_name!], options: nil)[0]
    let scale  = UIScreen.main.scale
    let size = CGSize(width: 50.0 * scale, height: 50.0 * scale)
    imageManager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in
        cell.imageView.image  = image
    }
    return cell
}

【问题讨论】:

    标签: ios swift photo phimagemanager


    【解决方案1】:

    您需要向照片库注册变更观察者。然后,您会在照片被删除、插入、更改或移动时收到通知。观察者需要继承自PHPhotoLibraryChangeObserver。然后你需要实现函数photoLibraryDidChange(_ changeInstance: PHChange)。如果您使用视图控制器作为观察者,您应该能够捕获集合视图中的所有更改,如下所示。下面的示例假设您拥有一个集合视图所需的所有 phAsset 数组,以显示其随时可用的图像

    class MyViewController : UIViewController, PHPhotoLibraryChangeObserver {
    
        func viewDidLoad() {
            ...
            PHPhotoLibrary.shared().register(self)
            ...
        }
    
        func photoLibraryDidChange(_ changeInstance: PHChange) {
            // Change notifications may be made on a background queue.
            // Re-dispatch to the main queue to update the UI.
            // Check for changes to the displayed album itself
            // (its existence and metadata, not its member self).
            guard let photos = photos else {return}
    
            // Check for changes to the list of assets (insertions, deletions, moves, or updates).
            if let changes = changeInstance.changeDetails(for: photos) {
                // Keep the new fetch result for future use.
                photos = changes.fetchResultAfterChanges
                if changes.hasIncrementalChanges {
                    // If there are incremental diffs, animate them in the collection view.
                    self.collectionView.performBatchUpdates({
                        // For indexes to make sense, updates must be in this order:
                        // delete, insert, reload, move
                        if let removed = changes.removedIndexes, removed.count > 0 {
                            print("photoLibraryDidChange: Delete at \(removed.map { IndexPath(item: $0, section:0) })")
                            self.collectionView.deleteItems(at: removed.map { IndexPath(item: $0, section:0) })
                        }
                        if let inserted = changes.insertedIndexes, inserted.count > 0 {
                            print("photoLibraryDidChange: Insert at \(inserted.map { IndexPath(item: $0, section:0) })")
                            self.collectionView.insertItems(at: inserted.map { IndexPath(item: $0, section:0) })
                        }
                        if var changed = changes.changedIndexes, changed.count > 0 {
                            print("photoLibraryDidChange: Reload at \(changed.map { IndexPath(item: $0, section:0) })")
                            // subtract removed indices
                            if let removed = changes.removedIndexes {
                                changed.subtract(removed)
                            }
                            self.collectionView.reloadItems(at: changed.map { IndexPath(item: $0, section:0) })
                        }
                        changes.enumerateMoves { fromIndex, toIndex in
                            print("photoLibraryDidChange: Move at \(IndexPath(item: fromIndex, section:0)) to \(IndexPath(item: toIndex, section:0 ))")
                            self.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.
                    ...
                }
            }
    
        }
    
        var photos : PHFetchResult<PHAsset>?
        weak var collectionView : UICollectionView!
    }
    

    目前您正在临时创建 PHAsset。您需要某种形式的永久 PHObject 才能使上述功能发挥作用。如果您将单个 PHAsset 存储在您的 photoArray 对象中,您可以在每个 PHAsset 上使用PHChange.changeDetails(for object: PHObject) 来捕获它们是否在应用程序运行时被删除。但是,这在应用程序的会话之间不起作用。

    您可以创建一个相册并将您的应用使用的所有图像存储在该相册中,而不是存储一组本地标识符。然后您可以查看该专辑的更改。

    顺便说一句,您遇到崩溃的原因是您要求空数组的数组元素 [0]。您可以通过检查 PHAsset.fetchAssets() 调用的结果是否计数大于零来避免崩溃。

    【讨论】:

    • 感谢@Spads 的快速回复。我尝试使用 PHPhotoLibraryChangeObserver 但它需要 PHFetchResult 才能使用,但我的核心数据中只有 PHAssets 的本地标识符,我通过它获取资产然后从中制作图像。如何将它与本地资产标识符一起使用。
    • 您可以将 PHChange.changeDetails(for object: PHObject) 用于单个 PHAsset。我会创建你所有的 PHAsset 并将它们存储在你的 photoArray 中。您可以在photoLibraryDidChange 中查看所有这些内容
    • 在我的回答末尾添加了一些 cmets
    • 如果应用程序暂停或终止时唤醒应用程序,iOS 是否会通知照片更改?如果没有,有解决方法吗?
    • @ViruMax 如果应用程序被暂停,它将在用户唤醒它时收到通知,如果我没记错的话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多