Getting Started with PhotoKit
In this tutorial, you’ll learn how to use PhotoKit to access and modify photos, smart albums and user collections. You’ll also learn how to save and revert edits made to photos. By Corey Davis.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Getting Started with PhotoKit
30 mins
- Getting Started
- Prepping the Photos App
- Getting PhotoKit Permissions
- Modifying Info.plist
- Requesting Authorization
- Understanding Assets
- Asset Data Models
- Fetching Assets and Asset Collections
- Prepping the Collection View
- Updating the Cell
- Fetching Images from Assets
- Displaying Album Assets
- Modifying Asset Metadata
- Change Requests
- Photo View Controller Change Observer
- Registering the Photo View Controller
- Photos View Controller Change Observer
- Registering the Photos View Controller
- Album View Controller Change Observer
- Album View Controller Registration
- Editing a Photo
- Saving Edits
- Undoing Edits
- Where to Go From Here?
Saving Edits
Use the editing output container created above to save the change to the library. Again, use a PHAssetChangeRequest
like you did for changing metadata earlier.
Still in PhotoViewController.swift, find saveImage()
and add the following to it:
// 1
let changeRequest: () -> Void = { [weak self] in
guard let self = self else { return }
let changeRequest = PHAssetChangeRequest(for: self.asset)
changeRequest.contentEditingOutput = self.editingOutput
}
// 2
let completionHandler: (Bool, Error?) -> Void = { [weak self] success, error in
guard let self = self else { return }
guard success else {
print("Error: cannot edit asset: \(String(describing: error))")
return
}
// 3
self.editingOutput = nil
DispatchQueue.main.async {
self.saveButton.isEnabled = false
}
}
// 4
PHPhotoLibrary.shared().performChanges(
changeRequest,
completionHandler: completionHandler)
- Like before, you handle the change within a code block. Create a
PHAssetChangeRequest
for the asset and apply the editing output container. - Create a completion handler to run after the change completes. Check for a successful result and print out the error if the result is not successful.
- If the change is a success, assign
nil
to the container property because it is no longer needed. Disable the save button, because there is nothing else left to save. - Call the library’s
performChanges(:completionHandler:)
and pass in the change request and completion handler.
Build and run. Navigate to a photo and tap the Apply Filter button. Tap the save button. iOS displays a dialog box asking for permission to modify the photo. Tap Modify.
Navigate back to All Photos and select the photo again. You should see that the modified image saved successfully.
Undoing Edits
There is one button left in the photo view controller that does not work: Undo. An undo, or revert, is also handled with … well, you probably know by now: PHAssetChangeRequest
.
Use the existence of asset change data to determine the Undo button’s enabled state. Find updateUndoButton()
and replace its contents with:
let adjustmentResources = PHAssetResource.assetResources(for: asset)
.filter { $0.type == .adjustmentData }
undoButton.isEnabled = !adjustmentResources.isEmpty
Each edit to an asset creates a PHAssetResource
object. The assetResources(for:)
returns an array of resources for the given asset. Filter the assets by the existence of adjustment data. The button’s isEnabled
property is set to true
if there are edits, otherwise it is false
.
It’s time to add the undo logic. Find undo()
and add this code to it:
// 1
let changeRequest: () -> Void = { [weak self] in
guard let self = self else { return }
let request = PHAssetChangeRequest(for: self.asset)
request.revertAssetContentToOriginal()
}
// 2
let completionHandler: (Bool, Error?) -> Void = { [weak self] success, error in
guard let self = self else { return }
guard success else {
print("Error: can't revert the asset: \(String(describing: error))")
return
}
DispatchQueue.main.async {
self.undoButton.isEnabled = false
}
}
// 3
PHPhotoLibrary.shared().performChanges(
changeRequest,
completionHandler: completionHandler)
By now, this pattern should be pretty familiar.
- Create a change request block to contain the change logic. For this example, you create a change request for the asset and call
revertAssetContentToOriginal()
. As you might expect, this requests that the asset change back to its original state. This does not affect metadata. - The completion handler checks for a successful result and disables the undo button if the result succeeded.
- Finally, instruct the library to perform the change.
Build and run. Select the photo to which you applied the filter. Tap Undo. Just like when you saved the asset earlier, iOS asks the user for permission to undo all changes.
Tap Revert. The image changes back to the original image.
Where to Go From Here?
Congratulations! You’ve covered a lot of ground in a short time. You can download the final project by clicking the Download Materials button at the top or bottom of the tutorial. You learned about:
- PhotoKit’s permission model.
- Accessing all photos, smart albums and user collections.
- Fetching images from assets.
- Modifying asset metadata.
- Editing an asset’s image.
- Saving asset modifications.
- Reverting asset modifications.
There is much more that PhotoKit has to offer, such as LivePhoto, video and the photo editing extension. Check out the PhotoKit documentation for more information:
Please share any comments or questions about this article in the forum discussion!