PhotoKit — este framework-ul Apple pentru lucrul cu mediateca pe iOS și macOS, oferind acces direct la fotografii, videoclipuri și Live Photos pe dispozitiv. Conform documentației Apple, framework-ul înlocuiește AssetsLibrary învechit și suportă iCloud, albume, editare și Change Tracking. PhotoKit asigură o API unificată pentru interogări, cache și modificări ale mediatecii cu sincronizare automată prin iCloud.
Principalele puncte
PhotoKit — framework Apple (introdus în iOS 8, macOS 10.11), care oferă o API orientată pe obiecte pentru lucrul cu mediateca de sistem. Spre deosebire de AssetsLibrary, PhotoKit tratează mediateca ca pe o bază de date: interogările returnează obiecte PHAsset, PHCollection, PHCollectionList, reprezentând conținutul și structura de stocare.
PhotoKit suportă toate tipurile de media: fotografii (JPEG, HEIF, RAW), videoclipuri (MOV, MP4), Live Photos și fotografii seriale. Framework-ul gestionează automat sincronizarea iCloud: dacă imaginea este stocată în iCloud, PhotoKit o solicită prin rețea și raportează progresul prin PHImageRequestOptions.progressHandler.
Caracteristica cheie a PhotoKit — modelul de date bazat pe PHObject cu identificator local (localIdentifier), care rămâne stabil între sesiuni. Aceasta permite salvarea referințelor la obiectele media și restaurarea lor după repornirea aplicației fără o nouă interogare.
PhotoKit este construit pe trei niveluri: model de date (PHObject), interogări (PHFetchResult) și modificări (PHPhotoLibrary.performChanges). Modelul de date este ierarhic: PHAsset (foto/video) se află în interiorul PHAssetCollection (album), albumele sunt grupate în PHCollectionList (folder).
Interogările se execută prin PHAsset.fetchAssets și PHAssetCollection.fetchAssetCollections. Toate metodele fetch sunt sincrone și returnează PHFetchResult, al cărui obiect execută imediat interogarea în baza de date a mediatecii. PHFetchResult suportă acces rapid după index (object(at:)) și enumerarea prin enumerateObjects.
PHFetchOptions — obiect pentru configurarea interogării: sortare (sortDescriptors), predicat (predicate), includerea mediilor ascunse și șterse (includeHiddenAssets, includeAllBurstAssets). Opțiunile fetch permit filtrarea după tipul de media: PHAssetMediaType.image, .video, .audio.
PhotoKit include un set de clase pentru acces, interogare și modificare a mediatecii. Înțelegerea fiecăreia dintre ele este necesară pentru o lucrare eficientă cu framework-ul.
PHAsset — obiect imutabil care reprezintă un singur conținut media. Conține metadate: mediaType, mediaSubtypes, creationDate, location, pixelWidth, pixelHeight, duration (pentru video), isFavorite, burstIdentifier. LocalIdentifier — cheie text stabilă, accesibilă chiar și după repornirea aplicației.
PHAssetCollection — grup de media: albume de sistem (Recents, Favorites, Selfies, Screenshots), albume de utilizator sau Moments (grupate automat după timp și loc). Atribute: localizedTitle, assetCollectionType, assetCollectionSubtype, startDate, endDate.
PHCollectionList — folder care conține albume (PHAssetCollection) sau alte foldere. Folosit rar, în principal pentru afișarea ierarhiei în interfața utilizatorului.
PhotoKit nu returnează UIImage direct din PHAsset — trebuie să solicitați imaginea prin PHImageManager. Aceasta garantează că imaginea este încărcată ținând cont de iCloud, cache și dimensiunea necesară.
| Component | Destinație | Caracteristică |
|---|---|---|
| PHImageManager.default() | Manager standard pentru interogări unice | Fără cache între interogări |
| PHCachingImageManager | Manager cu preîncărcare pentru colecții | startCachingImages pentru derulare lină |
| PHImageRequestOptions | Setări interogare: dimensiune, mod, livrare | synchronous, deliveryMode, progressHandler |
| PHImageRequestID | Identificator de interogare pentru anulare | cancelImageRequest(PHImageRequestID) |
PHImageManager suportă trei moduri de livrare: opportunistic (mai întâi versiunea redusă, apoi cea completă), highQualityFormat (doar calitate completă) și fastFormat (cea mai rapidă versiune disponibilă). Pentru colecții utilizați întotdeauna PHCachingImageManager cu preîncărcarea imaginilor pentru celulele vizibile.
PhotoKit este utilizat pentru crearea de galerii personalizate, editoare și aplicații pentru lucrul cu media. Să analizăm trei scenarii cheie.
PHAsset.fetchAssets cu PHFetchOptions și sortare după data creării — interogare de bază pentru construirea unei galerii foto personalizate. PHFetchResult suportă lazy-loading și acces în flux.
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("Găsite \(allPhotos.count) fotografii")
allPhotos.enumerateObjects { asset, index, stop in
print("Fotografia \(index): \(asset.localIdentifier)")
}
PHFetchResult — container thread-safe. Accesul la obiecte după index prin object(at:) nu blochează UI, dar solicitarea imaginii prin PHImageManager trebuie executată asincron.
PHCachingImageManager — subclasă a PHImageManager cu metodele startCachingImages și stopCachingImages pentru preîncărcare. Utilizat în UICollectionView pentru derulare lină.
let cachingManager = PHCachingImageManager()
let targetSize = CGSize(width: 200, height: 200)
// Preîncărcare pentru celule vizibile
cachingManager.startCachingImages(
for: visibleAssets,
targetSize: targetSize,
contentMode: .aspectFill,
options: nil
)
// Solicitare imagine prin PHImageRequestOptions cu fallback iCloud
let requestOptions = PHImageRequestOptions()
requestOptions.deliveryMode = .opportunistic
requestOptions.isNetworkAccessAllowed = .true
requestOptions.progressHandler = { progress, error, stop, info in
DispatchQueue.main.async {
print("Se încarcă din iCloud: \(progress * 100)%")
}
}
let requestID = cachingManager.requestImage(
for: asset,
targetSize: targetSize,
contentMode: .aspectFill,
options: requestOptions
) { image, info in
print("Imagine primită: \(image?.size ?? .zero)")
}
Modificările în mediatecă se execută prin PHPhotoLibrary.shared().performChanges în interiorul blocului changeRequest. Toate operațiile sunt grupate și aplicate tranzacțional.
PHPhotoLibrary.shared().performChanges {
let changeRequest = PHAssetChangeRequest(for: asset)
changeRequest.isFavorite = .true
} completionHandler: { success, error in
if success {
print("Adăugat la favorite")
}
}
PhotoKit oferă un mecanism de observare a modificărilor în mediatecă prin protocolul PHPhotoLibraryChangeObserver. La orice modificare (creare, ștergere, editare) se apelează metoda photoLibraryDidChange cu obiectul PHChange.
PHChange conține changeDetails pentru fiecare tip de interogare: PHFetchResultChangeDetails cu removedIndexes, insertedIndexes, changedIndexes. Aceasta permite aplicarea modificărilor în UI cu animație: performBatchUpdates cu move, insert, delete pentru 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
// Aplicați modificările la collectionView
}
}
}
PhotoKit suportă editarea media prin mecanismul PHContentEditingInput și PHContentEditingOutput. Aplicația solicită editingInput cu datele originale, aplică modificările și salvează rezultatul prin editingOutput. Framework-ul păstrează automat originalul, permițând utilizatorului să anuleze modificările prin resetare la original.
Fotografiile RAW (DNG, CR2, NEF) sunt suportate prin PHAssetResourceManager, care oferă acces la fișierul RAW original. Pentru procesarea RAW se recomandă utilizarea CoreImage cu filtrul CIRAWFilter, care suportă ajustarea temperaturii, expunerii și clarității. PhotoKit suportă și extensii de editoare prin Photo Editing Extension (iOS) — aplicația poate fi apelată din editorul de sistem pentru procesarea fotografiei sau videoclipului selectat.
PhotoKit — un framework puternic, dar consumator de resurse. Utilizarea incorectă poate duce la încetiniri la derulare și consum excesiv de memorie. Urmați recomandările pentru performanță optimă.
PHLivePhoto — necesită o interogare separată prin PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:). Nu solicitați Live Photo pentru celulele unde se afișează doar fotografia — utilizați PHLivePhotoBadge pentru indicare.
Întrebări frecvente
PhotoKit — un framework modern Apple pentru lucrul cu mediateca, introdus în iOS 8. Spre deosebire de AssetsLibrary învechit, PhotoKit oferă modelul obiectual PHAsset, PHFetchResult cu căutare rapidă, suport iCloud și Change Tracking pentru observarea modificărilor.
Apelați PHPhotoLibrary.requestAuthorization(for: .readWrite) cu procesare în callback. După obținerea statusului .authorized puteți executa interogări PHAsset.fetchAssets. Pentru scriere este necesar accesul .readWrite. Pentru doar citire — .addOnly.
Utilizați PHImageManager.default().requestImage cu parametrii: asset, targetSize, contentMode și PHImageRequestOptions. Metoda asincronă returnează PHImageRequestID, permițând anularea interogării. Pentru colecții utilizați PHCachingImageManager cu preîncărcare.
Înregistrați observatorul prin PHPhotoLibrary.shared().register(self) și implementați protocolul PHPhotoLibraryChangeObserver. În metoda photoLibraryDidChange veți primi PHChange cu changeDetails pentru fiecare fetchResult și aplicați modificările în UI cu animație.
În PHImageRequestOptions setați isNetworkAccessAllowed = true și progressHandler pentru urmărirea încărcării din iCloud. La derularea rapidă dezactivați accesul la rețea și încărcați doar versiunile locale pentru a evita întârzierile la derulare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și