PHAssetChangeRequest完成后,PHAsset没有反映更改

4
在文档中写道:

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

然而,在完成处理程序内部(以及完成处理程序之后),我的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)资产不是最喜欢的,然后2)请求是最喜欢的,3)资产仍然不是最喜欢的,4)资产仍然不是最喜欢的,5)资产仍然不是最喜欢的。
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

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

2
这是Photos框架中的一个bug。我认为这是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: 方法来获取更新后的资源,以查看正确的结果。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接