Search code examples
iosobjective-cexifphphotolibrary

EXIF Data not saving with image?


I want save some string with image in particular album. so I used [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ to add assets.

but when I get photos from album it doesn't have exif data.

my code for save EXIF data is here . Any answer please.

- (void)addImageToCameraRoll:(UIImage *)image didfinish:(NSString *)albumName {

    void (^saveBlock)(PHAssetCollection *assetCollection) = ^void(PHAssetCollection *assetCollection) {

        NSData* jpeg = UIImageJPEGRepresentation(image, 1.0f);

        CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) jpeg, NULL);
        CFStringRef imageType = CGImageSourceGetType(source);
        NSDictionary *metadata = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL));
        NSMutableDictionary *metadataAsMutable = [metadata mutableCopy];

        NSMutableDictionary *EXIFDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
        NSMutableDictionary *GPSDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyGPSDictionary]mutableCopy];

        if(!EXIFDictionary){
            //if the image does not have an EXIF dictionary (not all images do), then create one for us to use
            EXIFDictionary = [NSMutableDictionary dictionary];
        }

        if(!GPSDictionary){
            GPSDictionary = [NSMutableDictionary dictionary];
        }

        [GPSDictionary setValue:[NSNumber numberWithFloat:1.1] forKey:(NSString*)kCGImagePropertyGPSLatitude];
        [GPSDictionary setValue:[NSNumber numberWithFloat:2.2] forKey:(NSString*)kCGImagePropertyGPSLongitude];
        [EXIFDictionary setValue:@"my string to exif" forKey:(NSString *)kCGImagePropertyExifUserComment];
        [metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
        [metadataAsMutable setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];

        NSMutableData *resultData = [NSMutableData data];
        CGImageDestinationRef imgDest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)(resultData), imageType, 1, NULL);

        //copy image data
        CGImageDestinationAddImageFromSource(imgDest, source, 0, (CFDictionaryRef) metadataAsMutable);
        BOOL success = CGImageDestinationFinalize(imgDest);
        UIImage * image1 = [[UIImage alloc] initWithData:resultData];



        //Add assets
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                        PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image1];



                        PHObjectPlaceholder *assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset;
                        PHAssetCollectionChangeRequest *albumChangeRequest =
                        [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
                        [albumChangeRequest addAssets:@[ assetPlaceholder ]];

        }

                completionHandler:^(BOOL success, NSError *error) {
                         if (!success) {
                                NSLog(@"Error creating asset: %@", error);
                         }else{

                         }
                }];
    };


    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.predicate = [NSPredicate predicateWithFormat:@"localizedTitle = %@", albumName];

    PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions];

    if (fetchResult.count > 0) {
        saveBlock(fetchResult.firstObject);
    }
    else {
        __block PHObjectPlaceholder *albumPlaceholder;
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
            albumPlaceholder = changeRequest.placeholderForCreatedAssetCollection;

        } completionHandler:^(BOOL success, NSError *error) {
            if (success) {
                PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[albumPlaceholder.localIdentifier] options:nil];
                if (fetchResult.count > 0) {
                    saveBlock(fetchResult.firstObject);
                }
            } else {
                NSLog(@"Error creating album: %@", error);
            }
        }];
    }
}

I am using PHImageManager for getting images.


Solution

  • To Save the detail with Photo using Photos framework, You have to write the image to a temporary file and add the metadata to the temporary file using CGImageDestinationAddImage.

    Then you can read the data from the temporary file and save it to the Photos library by using [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL].