Swift: How to Retrieve Metadata from Album Images in iOS 7+

A recent project that I've been working on involves capture and storage of images. As part of the app, I needed to save and retrieve metadata from an image regardless of its origin, be it directly from the camera, or the user's camera roll albums.

Whilst this seems a relatively straight-forward task, it had me perplexed for a little while, so I wanted to share the eventual solution. This has been tested on iOS 7 and 8, and uses Swift 1.2.

Note If you target only iOS 8 upward, you can use Swift's new PhotoLibrary class.

When interacting with the photo library, the magic happens in the imagePickerController delegate method. This method is called after an image is captured using the camera, or selected from the photo library.

Lets set up the method structure.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
// ...next code here...
picker.dismissViewControllerAnimated(true, completion: nil);
}

As it stands, this will dismiss the previous and current views as soon as the method is called. We can easily get the metadata for a camera image by insert the following into the imagePickerController method.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){

imagePicker.dismissViewControllerAnimated(true, completion: nil)

if (picker.sourceType == .camera){
var metadata = info[UIImagePickerControllerMediaMetadata] as! NSDictionary
} else {
// ... next code here
}

picker.dismissViewControllerAnimated(true, completion: nil);
}

This code grabs the metadata from the current image and stores it in the metadata variable.

Picking from an Album

Next we need to get the metadata from an image if it has been picked from the user's photo library. To do this, we first need to get the local reference URL of the image, which locates it on the device. Within the else block above, add the following code

var referenceURL : NSURL = info[UIImagePickerControllerReferenceURL] as! NSURL

With the internal reference URL, we can now access the image metadata. For this we need to use the ALAssetLibrary class. This class controls access to the device's internal photo and video library.

You can find out more about ALAssetsLibrary here

Under the previous declaration add the following variable and instantiate it.

var library:ALAssetsLibrary? = ALAssetsLibrary()

We're now ready to get the data. After the else blocks library declaration add the structure of our closure.

library!.assetForURL(referenceURL, resultBlock: { (asset : ALAsset!) -> Void in
// ...other code here
})
{
(error : NSError!) -> Void in
}

Here we've passed the referenceURL into the block, and added basic error trapping to ensure that any errors don't crash our app. We can now access the image metadata by calling metadata() on it:

library!.assetForURL(referenceURL, resultBlock: { (asset : ALAsset!) -> Void in var rep : ALAssetRepresentation = asset.defaultRepresentation()
var metadata : NSDictionary = rep.metadata()
})
{
(error : NSError!) -> Void in
}

Here, the rep variable is assigned the default representation of our image. This in turn contains the metadata, from which we can extract our required information, or simply pass through to other methods to use.

And that's it, you can now have usable metadata for an image, regardless of its origin.

A full copy of the code can be seen in this gist.