In the docs it says:
After Photos runs the change block and calls your completion handler, the asset’s state reflects the changes that you requested in the block.
However, inside the completion handler (as well as after the completion handler), my PHAsset hasn't changed. Here's the code I'm using to change the Favorite status, and it's pulled from PHAsset docs page.
- (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);
}];
}
The -dispatchAfter:
and -dispatchMain:
functions above are just convenience functions that call gcd
functions to perform the block asynchronously after a certain amount of time or perform the block on the main UI thread.
When I run the code, I see that it starts 1) Asset is Not Fav, then 2) Request is Fav, 3) Asset is still Not Fav, 4) Asset is still Not Fav, 5) Asset is still Not Fav.
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
What am I doing wrong? Why isn't my asset object updating?
This is a bug in the Photos framework. I believe it's a 9.2 regression. In all previous releases the favorite
status is properly updated in the completion block as you expected and as the documentation states.
However, I did find a workaround. In photoLibraryDidChange
, note that change details are delivered for this asset after modifying favorite
. And you'll note that the objectAfterChanges
does have the new favorite
status. Therefore, instead of updating your UI immediately after the change request succeeds, update it after the change details are delivered. For example:
//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()
}
}
}