PHAssetChangeRequest 完成后 PHAsset 不反映更改

Posted

技术标签:

【中文标题】PHAssetChangeRequest 完成后 PHAsset 不反映更改【英文标题】:PHAsset doesn't reflect change after PHAssetChangeRequest completes 【发布时间】:2015-11-07 05:42:01 【问题描述】:

在文档中它说:

在照片运行更改块并调用您的完成处理程序后, 资产的状态反映了您在 块。

但是,在完成处理程序内部(以及完成处理程序之后),我的 PHAsset 没有改变。这是我用来更改收藏状态的代码,它来自 PHAsset 文档页面。

- (IBAction)touchedButtonFavoritePhoto:(id)sender 
    AssetViewController *vc = self.viewControllers[0];
    PHAsset *asset = vc.asset;

    NSLog(@"touched fav 1: %d", asset.favorite);

    [[phphotoLibrary sharedPhotoLibrary] performChanges:^
        // Create a change request from the asset to be modified.
        PHAssetChangeRequest *request = [PHAssetChangeRequest changeRequestForAsset:asset];
        // Set a property of the request to change the asset itself.
        request.favorite = !asset.favorite;
        NSLog(@"touched fav 2: %d", request.favorite);

     completionHandler:^(BOOL success, NSError *error) 
        NSLog(@"Finished updating asset. %@: %d", (success ? @"Success." : error), asset.favorite);
        NSLog(@"touched fav 3: %d", asset.favorite);

        [self dispatchMainSynchronously:NO usingBlock:^
            [self updateFavoriteButtonForAsset:asset];
            NSLog(@"touched fav 4: %d", asset.favorite);
        ];
    ];

    [self dispatchAfter:2.0 usingBlock:^
        NSLog(@"touched fav 5: %d", asset.favorite);
    ];

上面的-dispatchAfter:-dispatchMain:函数只是调用gcd函数在一定时间后异步执行块或在主UI线程上执行块的便利函数。

当我运行代码时,我看到它开始 1) Asset is Not Fav,然后 2) Request 是 Fav,3) Asset 仍然不是 Fav,4) Asset 仍然不是 Fav,5) Asset 仍然不是喜欢。

AppName[6155:3741600] startingPage.asset: <PHAsset: 0x1265f1b30> 4DFE1BBF-C16B-4150-8350-3FF1291B63B6/L0/001 mediaType=1/0, sourceType=1, (3264x2447), creationDate=2015-01-19 00:42:26 +0000, location=1, hidden=0, favorite=0 
AppName[6155:3741600] touched fav 1: 0
AppName[6155:3741879] touched fav 2: 1
AppName[6155:3741879] Finished updating asset. Success.: 0
AppName[6155:3741879] touched fav 3: 0
AppName[6155:3741600] touched fav 4: 0
AppName[6155:3741600] touched fav 5: 0

我做错了什么?为什么我的资产对象没有更新?

【问题讨论】:

【参考方案1】:

这是照片框架中的一个错误。我相信这是一个 9.2 的回归。在所有以前的版本中,favorite 状态在完成块中按照您的预期和文档状态正确更新。

但是,我确实找到了解决方法。在photoLibraryDidChange 中,请注意,在修改favorite 后会为该资产提供更改详细信息。您会注意到objectAfterChanges 确实具有新的favorite 状态。因此,与其在更改请求成功后立即更新您的 UI,不如在交付更改详细信息后更新它。例如:

//MARK: PHPhotoLibraryChangeObserver

func photoLibraryDidChange(changeInstance: PHChange) 
    guard let photoAsset = self.asset,
        let changeDetails = changeInstance.changeDetailsForObject(photoAsset)
        else  return 

    dispatch_async(dispatch_get_main_queue()) 
        self.asset = changeDetails.objectAfterChanges as? PHAsset

        //self.asset now has the proper favorite status
        self.updateFavoriteButton()

        if changeDetails.assetContentChanged 
            self.updateImage()
        
    

【讨论】:

【参考方案2】:

实际上,资产的属性发生了变化,但是当 PHPhotoLibrary 没有随着更改对其进行修改时,它不会出现。

您可以尝试通过调用 PHAsset 的 fetchAssetsWithLocalIdentifiers: 方法来获取更新的资产以查看正确的结果。

【讨论】:

但是文档说资产应该反映 performChanges 块内请求的更改。为什么我需要重新获取它? 是的,你提到的我在文档中也看到了。我还没有弄清楚。我只做了一个关于设置更改的快速测试,并在照片应用程序中看到了结果,照片的属性最终确实发生了变化...... 是的,但“最终”对我的用户的 UI 并没有真正的帮助。 :) 我认为您可以通过 fetchAssetsWithLocalIdentifiers: 获取带有更新信息的 PHAsset,替换存储中存在的 PHAsset 并自行触发 UI 更新。 通过fetchAssetsWithLocalIdentifiers 强制重新获取不起作用 - 之后favorite 状态仍然是旧值。

以上是关于PHAssetChangeRequest 完成后 PHAsset 不反映更改的主要内容,如果未能解决你的问题,请参考以下文章

PHAssetChangeRequest 以低分辨率保存

Swift:HEIC 图像的 PHAssetChangeRequest 失败

创建视频资产时,PHAssetChangeRequest 始终返回 nil

iOS 8 照片库 - 使用 PHAssetChangeRequest 添加资产时出错

将视频资产保存到图库后检索

照片错误是啥意思:无法获得资产 XPC 代理