Active Filters: Photos


#58: Photo Editing Extensions 🎑📝


Photo Editing Extensions are a powerful way for apps to integrate with the system Photos app. Users can begin editing a photo, jump into a third-party extension, and return seamlessly back to the system editing interface. Let's try making one.

We begin by adding a new Photo Editing Extension target to our project.

Our extension will use CoreImage (covered in Bite #32) to convert a photo to black and white. The basic workflow goes like this:

  1. User launches our extension while editing inside
  2. a PHContentEditingInput object is handed to us via the startContentEditingWithInput... function
  3. User performs the edits they would like using our view controller
  4. User taps Done button (provided by the system)
  5. System asks us for a PHContentEditingOutput object containing our changes to the image via finishContentEditingWithCompletionHandler.

Let's move on to the code.

Along with the input object, we also receive a placeholderImage which we'll use as the initial image in our own image view.

func startContentEditingWithInput(contentEditingInput: PHContentEditingInput?, placeholderImage: UIImage) {
  input = contentEditingInput
  imageView.image = placeholderImage

After processing, we create an output using the intial input object we were handed, and write our modified image to it's content URL.

let output = PHContentEditingOutput(contentEditingInput: input)

  atomically: true

Lastly, we describe our adjustments, so we can be a good citizen in's non-destructive editing world.

output.adjustmentData = PHAdjustmentData(
  formatIdentifier: NSBundle.mainBundle().bundleIdentifier!,
  formatVersion: "1.0",
  data: "Grayscale".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

Download the complete project here:


#33: Photos Framework Basics 🗻


The Photos Framework is the modern equivalent to the old Assets Library Framework. It's how you access and interact with the user's photo library on iOS and OS X. Here are a few examples of things you can do with it:

Retrieve All Albums

let fetchOptions = PHFetchOptions()

let albums = PHAssetCollection.fetchAssetCollectionsWithType(
  subtype: .Any,
  options: fetchOptions

Mark a Photo As A Favorite

  let request = PHAssetChangeRequest(forAsset: photo)
  request.favorite = true
}, completionHandler: { (successful, error) in })

Changes must happen asynchronously when working with the Photos Framework so we use a PHAssetChangeRequest to mark a photo as a favorite.

Retrieve an Image at Specific Size

let manager = PHCachingImageManager()

  targetSize: CGSizeMake(50.0, 50.0),
  contentMode: PHImageContentMode.AspectFill,
  options: nil,
  resultHandler: {
    (image: UIImage?, userInfo: [NSObject : AnyObject]?) in
    // yay image!

We didn't specify any options there, but you can use the PHImageRequestOptions to customize if you'd like to allow loading images over the network, as well as get a progress callback as they are downloaded.