Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2022 Photos & Camera

WWDC22 · 10 min · Photos & Camera

Discover PhotoKit change history

PhotoKit can help you build rich, photo-centric features. Learn how you can easily track changes to image assets with the latest APIs in PhotoKit. We’ll introduce you to the PHPhotoLibrary change history API and demonstrate how you can persist change tokens across launches to help your app recognize additions, deletions, and updates to someone’s photo library. To learn more about Photos library integration, be sure to watch "What’s new in the Photos picker" from WWDC22 and "Improve access to Photos in your app" from WWDC21.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 8 snippets

Tracking photo library changes swift · at 0:01 ↗
// Discover added assets
let options = PHFetchOptions()
options.predicate = NSPredicate(format: "creationDate > %@", lastLaunchDate as CVarArg)
let insertedAssets = PHAsset.fetchAssets(with: options)
Tracking photo library changes (2) swift · at 0:02 ↗
let fetchResult = PHAsset.fetchAssets(with: localIdentifiers, options: nil)
// Discover all modified and deleted assets
fetchResult.enumerateObjects { asset, idx, stop in
    if asset.modificationDate?.compare(lastLaunchDate) == .orderedDescending {
        // Asset could have been modified
    }
    if !localIdentifiers.contains(asset.localIdentifier) {
        // Asset could have been deleted
    }
}
Fetching persistent changes using persistent change token swift · at 0:03 ↗
let persistentChanges = try! PHPhotoLibrary.shared().fetchPersistentChanges(since: self.lastStoredToken)

for persistentChange in persistentChanges { 
   if let changeDetails = persistentChange.changeDetails(for: PHObjectType.asset) {
        let updatedIdentifiers = changeDetails.updatedLocalIdentifiers
        let deletedIdentifiers = changeDetails.deletedLocalIdentifiers
        let insertedIdentifiers = changeDetails.insertedLocalIdentifiers
    }
}

// After processing change details
self.lastStoredToken = lastPersistentChange.changeToken
Identifying important changes swift · at 0:04 ↗
// Get last stored change token
let changeToken = self.lastStoredToken

// Fetch persistent changes
let persistentChanges = try!   
         library.fetchPersistentChanges(since: changeToken)

for persistentChange in persistentChanges {
    // Grab change details and process updates
}
Using inserted identifiers swift · at 0:05 ↗
let insertedAssets = PHAsset.fetchAssets(with: insertedIdentifiers, options: nil)
insertedAssets.enumerateObjects { asset, idx, stop in
   for hike in hikes {
        let dateInterval = NSDateInterval(start: hike.startDate, end: hike.endDate)
        if dateInterval.contains(asset.creationDate) {
            // This hike contains a new added asset
        }
    }
}
Using updated identifiers swift · at 0:06 ↗
let updatedAssets = PHAsset.fetchAssets(with: updatedIdentifiers, options: nil)
updatedAssets.enumerateObjects { asset, idx, stop in
    if asset.hasAdjustments {
        // This asset has edits
    }
}
Using deleted identifiers swift · at 0:07 ↗
for deletedIdentifier in deletedIdentifiers {
    for collage in collages {
        if collage.assetLocalIdentifiers.contains(deletedIdentifier) {
            // This collage needs to be redrawn
        }
    }
}
Handling errors swift · at 0:08 ↗
do {
    let persistentChanges = try library.fetchPersistentChanges(since: changeToken)
} catch PHPhotosError.persistentChangeTokenExpired,
        PHPhotosError.persistentChangeDetailsUnavailable {
    let fetchResult = PHAsset.fetchAssets(with: trackedIdentifiers, options: options)
    // Use fetch result
}

Resources