Swift 实现PHPhotoLibraryChangeObserver的结构

Swift 实现PHPhotoLibraryChangeObserver的结构,swift,photokit,Swift,Photokit,我的模型有一个结构,它需要符合一个仅为NSObject的协议 我正在寻找一个可行的替代方案,以将模型转换为类。这些要求是: 将模型保持为值类型 调用photoLibraryDidChange时更新模型 如果PHPhotoLibraryChangeObserver不要求实现为NSObject,这将是理想的实现 struct Model: PHPhotoLibraryChangeObserver { var images:[UIImages] = [] fileprivate v

我的模型有一个结构,它需要符合一个仅为NSObject的协议

我正在寻找一个可行的替代方案,以将模型转换为类。这些要求是:

  • 将模型保持为值类型
  • 调用
    photoLibraryDidChange
    时更新模型
  • 如果
    PHPhotoLibraryChangeObserver
    不要求实现为NSObject,这将是理想的实现

    struct Model: PHPhotoLibraryChangeObserver {
    
        var images:[UIImages] = []
    
        fileprivate var allPhotos:PHFetchResult<PHAsset>?
    
        mutating func photoLibraryDidChange(_ changeInstance: PHChange) {
            let changeResults = changeInstance.changeDetails(for: allPhotos)
            allPhotos = changeResults?.fetchResultAfterChanges
            updateImages()
        }
    
        mutating func updateImages() { 
            // update self.images
            ...
        }
    
    }
    
    我在
    photoLibraryDidChange
    中设置了一个断点,但它并没有到达那里。我还检查了
    pkAdapter
    始终是同一个对象,并且不会在“更改时复制”时重新初始化

    **编辑:添加模型视图**

    这是modelview中负责模型管理的相关部分

    
    类ModelView:ObservableObject{
    @已发布的var模型=模型()
    init(){
    self.model.startFetching()
    }
    var图像:[UIImage]{
    自我模型
    }
    ...
    }
    
    编辑:解决了更新问题


    这是模拟器中的一个错误。。。在一台真正的设备上,它可以工作

    我最终得到了两种可能的设计:

  • 将PhotoKit接口与模型完全分离,让modelview管理并连接两者,因为模型视图可以访问模型实例
  • 创建一个PhotoKit接口作为模型的var,并将PhotoKit接口生成的可变数据推送到其中,这样就可以使用转义闭包对其进行更改。该模型从未从接口调用,只是通过计算机属性公开PhotoKit中的数据
  • 我将在下面展示两个示例实现。他们在很多方面都很幼稚,每次更新PhotoLibrary时都会刷新所有图片,从而忽略性能问题。实现适当的增量更新(以及其他优化)只会使代码变得混乱,并且不会提供关于原始问题解决方案的额外见解

    断开PhotoKit接口的连接

    模型视图

    类模型视图:observeObject{
    var pkSubscription:是否可以取消?
    private var pkAdapter=PhotoKitAdapter()
    @已发布的var模型=模型()
    init(){
    pkSubscription=self.pkAdapter.objectWillChange.sink{uu}in
    DispatchQueue.main.async{
    self.model.reset()
    对于self.pkAdapter.images中的img{
    self.model.append(uiimage:img)
    }
    }
    }
    self.pkAdapter.startFetching()
    }
    }
    
    模型

    结构模型{ 专用(设置)var图像:[UIImage]=[] 变异函数追加(uiimage:uiimage){ images.append(uiimage) } 变异函数重置(){ 图像=[] } } PhotoKit接口

    类PhotoKitAdapter:NSObject、PHPhotoLibraryChangeObserver、ObservableObject{
    var allPhotos:PHFetchResult?
    变量图像:[UIImage]=[]
    func photoLibraryDidChange(changeInstance:PHChange){
    DispatchQueue.main.async{
    如果让changeResults=changeInstance.changeDetails(对于:self.allPhotos!){
    self.allPhotos=changeResults.fetchResultAfterChanges
    self.updateImages()
    self.objectWillChange.send()
    }
    }
    }
    func startFetching(){
    PHPhotoLibrary.requestAuthorization{状态在中
    如果状态==。已授权{
    让allPhotosOptions=PHFetchOptions()
    AllPhotoOptions.sortDescriptors=[NSSortDescriptor(键:“creationDate”,升序:false)]
    self.allPhotos=PHAsset.fetchAssets(带:allphotoOptions)
    PHPhotoLibrary.shared()寄存器(自)
    self.updateImages()
    }
    }
    }
    fileprivate func appendImage(p:PHAsset){
    //这实际上会附加图像的多个副本,因为
    //对于同一资产,它会被多次调用。
    //需要对资产进行适当的跟踪
    设pm=PHImageManager.default()
    如果p.mediaType==.image{
    requestImage(for:p,targetSize:CGSize(宽:1024,高:768),contentMode:.默认值,选项:nil){
    图像,在
    如果让im=image{
    self.images.append(im)
    self.objectWillChange.send()
    }
    }
    }
    }
    fileprivate func updateImages(){
    self.images=[]
    如果让ap=所有照片{
    
    对于0中的索引。我正在尝试将PhotoKit必须更改的唯一可变数据推送到充当委托的引用类型属性。模型的其余部分可以异步处理它,以便它可以访问委托中的数据,而无需传递self(模型)到PhotoKit。我写了到目前为止的结果。似乎是可行的,除了
    photoLibraryDidChange
    没有被调用…肯定有一个愚蠢的错误,我只是看不出它可能取决于你的结构是如何传递的?记住,它是一个结构,所以每个任务都会复制一个。你能展示更多关于模型是如何维护的,以及如何为我调试并检查了适配器类是否多次实例化。Swift在更改时进行复制时,应将指向引用类型属性的指针转移到新值。情况似乎是这样。我还显式请求了适配器对象的id,在对模型进行了多次变异后,它是相同的。因此排除多个副本和丢失的参考。模拟器错误。在真实的设备上它可以工作…真是浪费时间