PhotoKit è un framework Apple per lavorare con la libreria multimediale su iOS e macOS, che fornisce accesso diretto a foto, video e Live Photos sul dispositivo. Secondo la documentazione Apple, il framework sostituisce il legacy AssetsLibrary e supporta iCloud, album, modifica e Change Tracking. PhotoKit fornisce un’API unificata per query, caching e modifiche della libreria multimediale con sincronizzazione automatica tramite iCloud.
Punti chiave
PhotoKit è un framework Apple (introdotto in iOS 8, macOS 10.11) che fornisce un’API orientata agli oggetti per lavorare con la libreria multimediale di sistema. A differenza di AssetsLibrary, PhotoKit tratta la libreria multimediale come un database: le query restituiscono oggetti PHAsset, PHCollection e PHCollectionList che rappresentano il contenuto e la struttura di archiviazione.
PhotoKit supporta tutti i tipi di media: foto (JPEG, HEIF, RAW), video (MOV, MP4), Live Photos e scatti in raffica. Il framework gestisce automaticamente la sincronizzazione iCloud: se un’immagine è archiviata in iCloud, PhotoKit la richiede tramite rete e segnala l’avanzamento tramite PHImageRequestOptions.progressHandler.
Una caratteristica fondamentale di PhotoKit è il modello dati basato su PHObject con un identificatore locale (localIdentifier) che rimane stabile tra le sessioni. Ciò consente di salvare riferimenti a oggetti multimediali e ripristinarli dopo il riavvio dell’app senza nuove query.
PhotoKit è costruito su tre livelli: modello dati (PHObject), query (PHFetchResult) e modifiche (PHPhotoLibrary.performChanges). Il modello dati è gerarchico: PHAsset (foto/video) risiede all’interno di PHAssetCollection (album) e gli album sono raggruppati in PHCollectionList (cartella).
Le query vengono eseguite tramite PHAsset.fetchAssets e PHAssetCollection.fetchAssetCollections. Tutti i metodi fetch sono sincroni e restituiscono PHFetchResult, che esegue immediatamente la query nel database della libreria multimediale. PHFetchResult supporta l’accesso rapido per indice (object(at:)) e l’enumerazione tramite enumerateObjects.
PHFetchOptions è un oggetto per configurare le query: ordinamento (sortDescriptors), predicato (predicate), inclusione di media nascosti ed eliminati (includeHiddenAssets, includeAllBurstAssets). Le opzioni fetch consentono di filtrare per tipo di media: PHAssetMediaType.image, .video, .audio.
PhotoKit include un insieme di classi per accedere, interrogare e modificare la libreria multimediale. Comprendere ciascuna di esse è essenziale per lavorare efficacemente con il framework.
PHAsset è un oggetto immutabile che rappresenta un singolo elemento multimediale. Contiene metadati: mediaType, mediaSubtypes, creationDate, location, pixelWidth, pixelHeight, duration (per video), isFavorite, burstIdentifier. LocalIdentifier è una chiave stringa stabile accessibile anche dopo il riavvio dell’app.
PHAssetCollection è un gruppo di media: album di sistema (Recents, Favorites, Selfies, Screenshots), album utente o Moments (raggruppati automaticamente per tempo e luogo). Attributi: localizedTitle, assetCollectionType, assetCollectionSubtype, startDate, endDate.
PHCollectionList è una cartella contenente album (PHAssetCollection) o altre cartelle. Viene usato raramente, principalmente per visualizzare la gerarchia nell’interfaccia utente.
PhotoKit non restituisce UIImage direttamente da PHAsset — è necessario richiedere un’immagine tramite PHImageManager. Ciò garantisce che l’immagine venga caricata con supporto iCloud, caching e dimensione richiesta.
| Componente | Scopo | Caratteristica |
|---|---|---|
| PHImageManager.default() | Gestore standard per richieste singole | Nessun caching tra le richieste |
| PHCachingImageManager | Gestore con precaricamento per collezioni | startCachingImages per scorrimento fluido |
| PHImageRequestOptions | Impostazioni richiesta: dimensione, modalità, consegna | synchronous, deliveryMode, progressHandler |
| PHImageRequestID | Identificatore richiesta per annullamento | cancelImageRequest(PHImageRequestID) |
PHImageManager supporta tre modalità di consegna: opportunistic (prima una versione ridotta, poi la completa), highQualityFormat (solo qualità completa) e fastFormat (versione più veloce disponibile). Per le collezioni, utilizzare sempre PHCachingImageManager con precaricamento delle immagini per le celle visibili.
PhotoKit viene utilizzato per creare gallerie personalizzate, editor e applicazioni multimediali. Esaminiamo tre scenari chiave.
PHAsset.fetchAssets con PHFetchOptions ordinato per data di creazione è la query di base per costruire una galleria fotografica personalizzata. PHFetchResult supporta il caricamento lazy e l’accesso in streaming.
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(
key: "creationDate",
ascending: .false
)]
options.predicate = NSPredicate(
format: "mediaType == %d",
PHAssetMediaType.image.rawValue
)
let allPhotos = PHAsset.fetchAssets(with: options)
print("Trovate \(allPhotos.count) foto")
allPhotos.enumerateObjects { asset, index, stop in
print("Foto \(index): \(asset.localIdentifier)")
}
PHFetchResult è un contenitore thread-safe. L’accesso agli oggetti per indice tramite object(at:) non blocca l’interfaccia utente, ma la richiesta di un’immagine tramite PHImageManager deve essere eseguita in modo asincrono.
PHCachingImageManager è una sottoclasse di PHImageManager con i metodi startCachingImages e stopCachingImages per il precaricamento. Viene utilizzato in UICollectionView per uno scorrimento fluido.
let cachingManager = PHCachingImageManager()
let targetSize = CGSize(width: 200, height: 200)
// Precaricamento per celle visibili
cachingManager.startCachingImages(
for: visibleAssets,
targetSize: targetSize,
contentMode: .aspectFill,
options: nil
)
// Richiedi immagine tramite PHImageRequestOptions con fallback iCloud
let requestOptions = PHImageRequestOptions()
requestOptions.deliveryMode = .opportunistic
requestOptions.isNetworkAccessAllowed = .true
requestOptions.progressHandler = { progress, error, stop, info in
DispatchQueue.main.async {
print("Download da iCloud: \(progress * 100)%")
}
}
let requestID = cachingManager.requestImage(
for: asset,
targetSize: targetSize,
contentMode: .aspectFill,
options: requestOptions
) { image, info in
print("Immagine ottenuta: \(image?.size ?? .zero)")
}
Le modifiche alla libreria multimediale vengono eseguite tramite PHPhotoLibrary.shared().performChanges all’interno di un blocco changeRequest. Tutte le operazioni vengono raggruppate e applicate in modo transazionale.
PHPhotoLibrary.shared().performChanges {
let changeRequest = PHAssetChangeRequest(for: asset)
changeRequest.isFavorite = .true
} completionHandler: { success, error in
if success {
print("Aggiunto ai preferiti")
}
}
PhotoKit fornisce un meccanismo per osservare le modifiche alla libreria multimediale attraverso il protocollo PHPhotoLibraryChangeObserver. Quando si verificano modifiche (creazione, eliminazione, modifica), viene chiamato il metodo photoLibraryDidChange con un oggetto PHChange.
PHChange contiene changeDetails per ogni tipo di query: PHFetchResultChangeDetails con removedIndexes, insertedIndexes, changedIndexes. Ciò consente di applicare le modifiche all’interfaccia utente con animazione: performBatchUpdates con move, insert, delete per UICollectionView.
class PhotosViewController: UIViewController {
var fetchResult: PHFetchResult>PHAsset>?
override func viewDidLoad() {
super.viewDidLoad()
PHPhotoLibrary.shared().register(self)
}
deinit {
PHPhotoLibrary.shared().unregisterChangeObserver(self)
}
}
extension PhotosViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let fetchResult,
let details = changeInstance.changeDetails(for: fetchResult)
else { return }
DispatchQueue.main.async {
self.fetchResult = details.fetchResultAfterChanges
// Applica modifiche a collectionView
}
}
}
PhotoKit supporta la modifica dei media attraverso il meccanismo PHContentEditingInput e PHContentEditingOutput. L’app richiede editingInput con i dati originali, applica le modifiche e salva il risultato tramite editingOutput. Il framework conserva automaticamente l’originale, consentendo agli utenti di annullare le modifiche ripristinando l’originale.
Le foto RAW (DNG, CR2, NEF) sono supportate tramite PHAssetResourceManager, che fornisce accesso al file RAW originale. Per l’elaborazione RAW, si consiglia di utilizzare CoreImage con il filtro CIRAWFilter, che supporta la regolazione di temperatura, esposizione e nitidezza. PhotoKit supporta anche le estensioni dell’editor tramite Photo Editing Extension (iOS) — un’app può essere richiamata dall’editor di sistema per elaborare una foto o un video selezionato.
PhotoKit è un framework potente ma dispendioso in termini di risorse. Un uso improprio può causare rallentamenti nello scorrimento e consumo eccessivo di memoria. Segui queste raccomandazioni per prestazioni ottimali.
PHLivePhoto richiede una richiesta separata tramite PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:). Non richiedere Live Photo per le celle che mostrano solo foto — usa PHLivePhotoBadge come indicatore.
Domande frequenti
PhotoKit è un moderno framework Apple per lavorare con la libreria multimediale, introdotto in iOS 8. A differenza del legacy AssetsLibrary, PhotoKit fornisce il modello a oggetti PHAsset, PHFetchResult con ricerca rapida, supporto iCloud e Change Tracking per osservare le modifiche.
Chiama PHPhotoLibrary.requestAuthorization(for: .readWrite) con un gestore di callback. Dopo aver ricevuto lo stato .authorized, puoi eseguire query PHAsset.fetchAssets. L’accesso in scrittura richiede il permesso .readWrite. Per sola lettura — .addOnly.
Usa PHImageManager.default().requestImage con parametri: asset, targetSize, contentMode e PHImageRequestOptions. Il metodo asincrono restituisce PHImageRequestID, consentendo di annullare la richiesta. Per le collezioni, usa PHCachingImageManager con precaricamento.
Registra un osservatore tramite PHPhotoLibrary.shared().register(self) e implementa il protocollo PHPhotoLibraryChangeObserver. Nel metodo photoLibraryDidChange, ricevi PHChange con changeDetails per ogni fetchResult e applica le modifiche all’interfaccia utente con animazione.
In PHImageRequestOptions, imposta isNetworkAccessAllowed = true e un progressHandler per monitorare l’avanzamento del download da iCloud. Durante lo scorrimento veloce, disabilita l’accesso alla rete e carica solo le versioni locali per evitare rallentamenti.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche