Dancing Around PhotoKit Potholes

December 18, 2018 • 12:00 AM

I was living in the creamy dreamland of how PhotoKit will gracefully help me make the one-tap photo editing tool, until I ran into a nasty bug that prevented most of my photo edits from persisting. Worst of all, there is no helpful error message, other than this spit out from PHPhotoLibrary.performChanges():

The operation couldn’t be completed. (Cocoa error -1.)

Hmmm. OK. Not helpful at all — not at least to an iOS development rookie like me. So I did a round of Googling, and to my surprise, there hasn’t been a lot of discussion about this issue. I gave Apple’s documentation a thorough read and found its official demo project.

Built it, ran it, and no Cocoa error anymore, not from my imported-from-camera photos taken in 2009. (I have 20,000 photos and 300 videoes sitting on my iCloud Photos Library, and it’s a healthy test ground for all kinds of media that may reside on an iPhone.)

But as I scrolled through the pile of photos to the most recent ones1 taken with the iPhone XS. Then I saw the same errors with Apple’s own demo project:

The operation couldn’t be completed. (Cocoa error -1.)

Well, that’s bummer… Time for yet another round of Googling!

The Buried Solution

Bake in your orientation

After struggling for two days, and a 10th round of Googling with a different set of keywords, (and after reading posts in Russian, Korean, Spanish, etc…) I’ve found a solution that actually worked.

This Stack Overflow question pointed to @vandadnp’s script, which I’ve modified for Swift 4.2:

func dataFrom(ciImage: CIImage) -> Data {
    let glContext = EAGLContext(api: .openGLES2)!
    let context = CIContext(eaglContext: glContext)
    let imageRef = context.createCGImage(ciImage, from: ciImage.extent)!
    let image = UIImage(cgImage: imageRef, scale: 1.0, orientation: .up)
    return image.jpegData(compressionQuality: 1.0)!
}

With plain words, this convoluted method removes metadata, especially the orientation information embedded into the image file, and sort of “bake in” the orientation to the image itself.

So why do we need to remove this information?

I knew I came across something about image orientation with Apple’s doc — there is a line of “important” notes in Apple’s documentation, conveniently tucked away in the docs for a tiny property:

Edited asset content must incorporate (or “bake in”) the intended orientation of the asset. That is, the orientation metadata (if any) that you write in the output image or video file must declare the “up” orientation, and the image or video data must appear right-side up when presented without orientation metadata.

I have reasons to believe that this is the reason that caused PhotoKit spitting out that Cocoa Error -1. Now everything works beautifully.

Provide PHAdjustmentData

Once the problem is solved, I went ahead and tested whether not providing adjustmentData parameter to the PHContentEditingOutput object will also result in the same Cocoa Error.

Well, it did. Every single time, even for the “naturally oriented” photos. So I guess it is quite important to provide at least something to the adjustmentData property, even when Apple’s doc does not specifically state the importance:

To allow a user to continue working with the edit later (for example, to adjust the parameters of a photo filter), create a PHAdjustmentData object describing the changes.

To me, it says the entire adjustmentData is a nice-to-have that facilitates state restoration of user’s operations on the image. Apparently, it is not some nice-to-have; it is mandatory to avoid a Cocoa Error.

Summary

So to avoid getting fed by the nasty Cocoa Error -1, there are apparently two things to keep in mind:

  1. Always provide some PHAdjustmentData to the PHContentEditingOutput object. Otherwise, there will be an error.
  2. Make sure your photo is rid of orientation data, with a helper method from @vandadnp.

At the very end, I hope Apple will try to address this convoluted expression in their documentation. Some clean-up with its own documents will go a long way — we have a step-by-step instruction here, an overview here, and an important piece of note tucked away here. There has to be a better way to organize this information.

Also please provide bug-free demo code.

  1. Apple’s demo project did not show the most recent photos first, which is quite understandable.