Reputation: 16256
I want to create a new asset in the photo library and apply adjustment data (edits) to it, without the user being prompted twice.
I am developing an iOS photo editing extension, and providing similar functionality in the container app.
For better code reuse and modularity, I am adopting a PHContentEditingController
-based flow on both the extension (required) and the container app, bundling all the shared components in an embedded framework that both the app and the extension link against (as recommended by Apple).
Unlike the app extension, which is "passed" an image to edit by the Photos app and executes under its supervision, the container app needs to request changes to the asset library, each resulting in the user being prompted for authorization.
On launch, the app offers the user two options for sourcing the image to edit:
(both options rely on UIImagePickerController
, of course)
Right now, the images read from the library undergo the same editing flow as they would within the app extension, with the only difference that my own UI code manually calls finishContentEditing(completionHandler:)
on the (shared) object that adopts the PHContentEditingController
protocol, and, on completion, it further calls the PHAssetLibrary
method performChanges(_:completionHandler)
(which triggers the authorization prompt).
This means that edits made within the container app can be reverted when re-editing the same image with the extension in the Photos app (and potentially vice-versa, too, once I get around supporting adjustment data).
For new images taken with the camera, however, I am taking a different approach. After applying the filters, I just save the result to the photo library using the legacy function:
UIImageWriteToSavedPhotosAlbum(_:_:_:_:)
(back from the time when argument labels weren't a thing yet :-)
The problem with this approach is that edits are always 'baked in' for images taken with the camera and edited within the app (the can't be reverted). This feels arbitrary and perhaps even confusing to the user, so I'm looking for a more unified approach.
I could save the photo to the library right after the user takes it, and from there use the same flow as with existing assets, but this means that I need to modiufy the library twice:
...which will result in the user being asked for permission twice: Once before editing the image, and once again on committing the edits.
So, my question is:
Is There a Way to Create a Library Asset "In One Go", Original Image and Adjustment Data?
Upvotes: 1
Views: 524
Reputation: 16256
Although I haven't tried this on my code yet (I have more urgent issues now), I seem to have found what seems to be the exact answer to my question in Apple's documentation for one of the initializers of the PHContentEditingOutput class:
init(placeholderForCreatedAsset: PHObjectPlaceholder)
From the docs:
Discussion
Use this method if you want to add a new asset to the Photos library with edited content, as opposed to editing the content of an asset after adding it to the library. For example, you might use this option if your app applies filters to photos it captures with the device camera—instead of saving only the filtered image to the Photos library, your app can save both the filtered and the original image, allowing the user to revert to the original image or apply different filters later.
Also:
Note
If your app edits the contents of assets already in the Photos library—including assets your app has itself recently added—Photos prompts the user for permission to change the asset’s content. If instead your app uses the init(placeholderForCreatedAsset:) method to create an asset with edited content, Photos recognizes your app’s ownership of the content and therefore does not need to prompt the user for permission to edit it.
I guess we all need a healthy dose of RTFM once in a while! :-)
Upvotes: 0