私のアプリは写真を撮ってカメラロールに保存し、EXIF メタデータを変更できるようにします。
AssetsLibrary を使用して写真を保存および変更します (基になる EXIF を変更する必要があるため、新しい PhotoKit API は使用できません。さらに、これはレガシー アプリであり、変更するには多くのリファクタリングが必要になります)。
私は Xcode 6.3.1 を iOS 8.3 SDK で使用しており、展開ターゲットは 6.1 です。
iOS 8.2 では、これがすべて機能しました。
iOS 8.3 では、メタデータの編集に失敗します。
アプリには、プライバシー設定で写真にアクセスする権限があります。
ユーザーが写真を変更し、アプリが写真を書き換えようとすると、iOS 8.3 では [アプリにこの写真の変更を許可する] ダイアログが表示されるようになりました。このダイアログは、iOS 8.2 では表示されませんでした。[変更] をクリックすると、写真は保存されますが、メタデータは消去されます。setImageData から返されるエラーもありません。写真が編集可能かどうかを確認します。
コードは次のとおりです。
-(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];
}
}
これをデバッグしているときに、UIImageJPEGRepresentation によって写真のサイズが 4 倍に拡大されているコードのバグに気付きました。これは、写真を再サンプリングしていたためです。そのため、元の画像バイトを取得するようにコードを変更し、メタデータを書き直しました。しかし興味深いことに、別のエラーが返されます。今回は setImageData がこのエラーを返します。
説明 : 「ユーザーがアクセスを拒否しました」。
根本的なエラー:「ALAssetsLibraryErrorDomain」コード -3311。
FailureReason : 「ユーザーはアプリケーションによるメディアへのアクセスを拒否しました」。
アプリがアセットを作成し、カメラロールにアクセスできるため、これは奇妙です。
繰り返しますが、このコードは 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];
}
}
Apple にバグレポートを提出しましたが、何の返事もありません。
これはこの質問に似ています: setImageData fails in iOS 8.3
誰かがこれの修正を知っていますか?
ありがとう、