In iOS 8, with the new PhotoKit, the way to create a new image is with -[PHPhotoLibrary performChanges:completionHandler]
, in this way:
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
// TODO set metadata?
} completionHandler:^(BOOL success, NSError *error) {
if(success)
{
// do stuff
}
}];
However, I can't find any documentation on how to set metadata on the image.
In the old ALAssetLibrary (which still works, and may still be the 'correct' way going forward), you would just use -[ALAssetLibrary writePhotoToSavedPhotosAlbum:metadata:completionBlock:]
, which allows you to pass in a metadata dictionary.
Is there an equivalent method in PhotoKit?
You can achieve the same result by using a temporary file. For example:
import Photos
import ImageIO
import MobileCoreServices
PHPhotoLibrary.sharedPhotoLibrary().performChanges ({
let temporaryPath = ... // a path in the App's documents or cache directory
let fileURL = NSURL.fileURLWithPath (temporaryPath)!
// custom UIImagePNGRepresentation function is implemented below
let PNGdataWithMetadata = UIImagePNGRepresentation (photo, copyright: "Image Copyright",
author: "Image Author", description: "Image Description")
let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL (fileURL)
}, completionHandler: { (success, error) in
// to-do: delete the temporary file
println ("completion \(success) \(error)")
})
// what the custom UIImagePNGRepresentation function does is create a PNG representation that contains the given metadata. The function assumes all functions return valid data
// to add the metadata to the PNG representation of the image we:
// 1. create the PNG representation and read the default values (these will include things like the image's size)
// 2. add the metadata items (see CGImageProperties Reference for the valid keys)
// 3. create an image destination where the new PNG will be created and assigned the metadata dictionary
public func UIImagePNGRepresentation (image : UIImage, # copyright : String, # author : String, # description : String) -> NSData {
// wrap the valid metadata values in a dictionary
var PNGmetadata = [String : AnyObject] ()
PNGmetadata [kCGImagePropertyPNGCopyright] = copyright
PNGmetadata [kCGImagePropertyPNGAuthor] = author
PNGmetadata [kCGImagePropertyPNGDescription] = description
let metadata = [kCGImagePropertyPNGDictionary as String : PNGmetadata]
return UIImagePNGRepresentation (image, metadata: metadata)
}
public func UIImagePNGRepresentation (image : UIImage, # metadata : [String : [String : AnyObject]]) -> NSData {
let imageSource = CGImageSourceCreateWithData (UIImagePNGRepresentation (image), nil)
let defaultAttributes = CGImageSourceCopyPropertiesAtIndex (imageSource, 0, nil) as NSDictionary
let extendedAttributes = defaultAttributes.mutableCopy () as NSMutableDictionary
for item in metadata {
extendedAttributes [item.0] = item.1
}
var outputPNGdata = NSMutableData ()
let imageDestination = CGImageDestinationCreateWithData (outputPNGdata, kUTTypePNG, 1, nil)
CGImageDestinationAddImageFromSource (imageDestination, imageSource, 0, extendedAttributes)
let success = CGImageDestinationFinalize (imageDestination)
assert (success, "Fail!")
return outputPNGdata
}
I'm copying-pasting code from my project, hopefully I'm not missing something.