iOS 8 Photos framework. Access photo metadata iOS 8 Photos framework. Access photo metadata ios ios

iOS 8 Photos framework. Access photo metadata


If you request a content editing input, you can get the full image as a CIImage, and CIImage has a property titled properties which is a dictionary containing the image metadata.

Sample Swift Code:

let options = PHContentEditingInputRequestOptions()options.networkAccessAllowed = true //download asset metadata from iCloud if neededasset.requestContentEditingInputWithOptions(options) { (contentEditingInput: PHContentEditingInput?, _) -> Void in    let fullImage = CIImage(contentsOfURL: contentEditingInput!.fullSizeImageURL)    print(fullImage.properties)}

Sample Objective-C Code:

PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];options.networkAccessAllowed = YES; //download asset metadata from iCloud if needed[asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {    CIImage *fullImage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];    NSLog(@"%@", fullImage.properties.description);}];

You'll get the desired {Exif}, {TIFF}, {GPS}, etc dictionaries.


I thought I'd share some code to read the metadata using the ImageIO framework in conjunction with Photos framework. You must request the image data using a PHCachingImageManager.

@property (strong) PHCachingImageManager *imageManager;

Request the image and use it's data to create a metadata dictionary

-(void)metadataReader{    PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:self.myAssetCollection options:nil];    [result enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndex:myIndex] options:NSEnumerationConcurrent usingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {        [self.imageManager requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {            NSDictionary *metadata = [self metadataFromImageData:imageData];                           NSLog(@"Metadata: %@", metadata.description);            NSDictionary *gpsDictionary = metadata[(NSString*)kCGImagePropertyGPSDictionary];            if(gpsDictionary){                NSLog(@"GPS: %@", gpsDictionary.description);            }            NSDictionary *exifDictionary = metadata[(NSString*)kCGImagePropertyExifDictionary];            if(exifDictionary){                NSLog(@"EXIF: %@", exifDictionary.description);            }            UIImage *image = [UIImage imageWithData:imageData scale:[UIScreen mainScreen].scale];            // assign image where ever you need...        }];    }];}

Convert NSData to metadata

-(NSDictionary*)metadataFromImageData:(NSData*)imageData{    CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)(imageData), NULL);    if (imageSource) {        NSDictionary *options = @{(NSString *)kCGImageSourceShouldCache : [NSNumber numberWithBool:NO]};        CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);        if (imageProperties) {            NSDictionary *metadata = (__bridge NSDictionary *)imageProperties;            CFRelease(imageProperties);            CFRelease(imageSource);            return metadata;        }        CFRelease(imageSource);    }    NSLog(@"Can't read metadata");    return nil;}

This has the overhead of grabbing the image, so it's not nearly as fast as enumerating your assets or collections, but it's something at least.


I prefer not to CIImage solution, but to ImageIO solution:

func imageAndMetadataFromImageData(data: NSData)-> (UIImage?,[String: Any]?) {    let options = [kCGImageSourceShouldCache as String: kCFBooleanFalse]    if let imgSrc = CGImageSourceCreateWithData(data, options as CFDictionary) {        let metadata = CGImageSourceCopyPropertiesAtIndex(imgSrc, 0, options as CFDictionary) as! [String: Any]        //print(metadata)        // let image = UIImage(cgImage: imgSrc as! CGImage)        let image = UIImage(data: data as Data)        return (image, metadata)    }    return (nil, nil)}

below is code to get data from PHAseet

func getImageAndMeta(asset: PHAsset){    let options = PHImageRequestOptions()    options.isSynchronous = true    options.resizeMode = .none    options.isNetworkAccessAllowed = false    options.version = .current    var image: UIImage? = nil    var meta:[String:Any]? = nil    _ = PHCachingImageManager().requestImageData(for: asset, options: options) { (imageData, dataUTI, orientation, info) in        if let data = imageData {            (image, meta) = imageAndMetadataFromImageData(data: data as NSData)            //image = UIImage(data: data)        }    }    // here to return image and meta}


matomo