My app takes pictures, saves them to the camera roll, and allows the modification of the EXIF metadata.
I use the AssetsLibrary to save and modify the photo (I can't use the new PhotoKit api because I need to modify the underlying EXIF, plus it's a legacy app and would require a lot of refactoring to change it).
I am using Xcode 6.3.1, with the iOS 8.3 SDK, deployment target of 6.1.
In iOS 8.2, all this worked.
In iOS 8.3, the editing of the metadata fails.
The app has permission in the Privacy settings to access Photos.
When a user modifies the photos, and the app tries to rewrite the photo, iOS 8.3 now shows the "Allow App to modify this photo" dialog. This dialog did not appear in iOS 8.2. If I click "Modify", the photo is saved, but the metadata is wiped. There is also no error returned from setImageData, and I check if the photo is editable.
Here is the code:
-(void)savePhoto:(ALAsset*)asset
{
ALAssetRepresentation* rep = [asset defaultRepresentation];
CGImageRef imageRef = [rep fullResolutionImage];
UIImage *image = [UIImage imageWithCGImage:imageRef];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
if ([asset isEditable])
{
[asset setImageData:imageData metadata:self.getMetadataDictionary completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error!=nil)
[self showErrorDialog:error title:@"Error saving photo" ];
[self closeSaveDialog];
}];
}
else
{
[self closeSaveDialog];
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Error saving photo" message:@"Photo is not editable" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
When debugging this, I noticed a bug in my code where the photo size was being increased by 4x by the UIImageJPEGRepresentation, because it was resampling the photo, so I changed the code to grab the original image bytes, and just rewrite the metadata. But interestingly, I get a different error back, this time setImageData returns this error.
Description : "User denied access".
Underlying error : "ALAssetsLibraryErrorDomain" Code -3311.
FailureReason : "The user has denied the application access to their media".
Which is strange, because the app created the asset, and it has acccess to the camera roll.
Again, this code works in iOS 8.2:
-(void)savePhoto:(ALAsset*)asset
{
ALAssetRepresentation* rep = [asset defaultRepresentation];
// New way handling updating photos, doesn't modify image data at all, only metadata
Byte *buffer = (Byte*)malloc((unsigned long)rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:(NSUInteger)rep.size error:nil];
NSData *imageData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
if ([asset isEditable])
{
[asset setImageData:imageData metadata:self.getMetadataDictionary completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error!=nil)
[self showErrorDialog:error title:@"Error saving photo" ];
[self closeSaveDialog];
}];
}
else
{
[self closeSaveDialog];
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Error saving photo" message:@"Photo is not editable" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
I submitted a bug report to Apple, but havn't heard anything back.
This is similar to this question : setImageData fails in iOS 8.3
Does anyone know of a fix for this?
Thanks,