Hi, Habr! In this article I decided to write about how to work with the gallery using the Photos framework. In this article we will look at the basic features of the framework: creating an album, saving, deleting and loading photos. If there are positive reviews, in the following parts I will write about working with live photos, videos, filtering, cache and other functions.
Class overview
To begin, consider the classes with which to work. In the Photos framework, all classes are inherited from the base class
PHObject , in which there is only one property - localIdentifier.
▍PHAsset
PHAsset is a data about a single object from the gallery - photo, video, live photo and so on. It is important to understand that
PHAsset is not a photo yet, it is only information about it.
▍PHAssetCollection
This is a set of
PHAsset objects. Such a set can be an album, a moment, a smart album.
')
▍PHPhotoLibrary
This is the class that provides access to query and change data from the gallery. Every time we want to change something in the gallery, we need to call the method
performChanges (changes: () → Void, completionHandler: (Bool, Error?) → Void) .
▍PHAssetCreationRequest
The class that allows you to make a request to create a new object (
PHAsset ) in the gallery.
▍PHAssetChangeRequest
The class that allows you to make a request to change the object in the gallery.
▍PHAssetCollectionChangeRequest
The class that allows you to make a request to change the collection of objects in the gallery.
▍PHImageManager
Allows you to get a photo or video associated with a specific
PHAsset .
▍PHFetchResult
Represents the wrapper above the
PHAsset list received as a result of the query.
Creating an album
First you need to check whether there is an album with the estate with which we want to create it:
let options = PHFetchOptions() options.predicate = NSPredicate(format: "title = %@", albumTitle) let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: options) if let album = collection.firstObject { // , }
If there is no album, then to create it we will need to create a query using the
PHAssetCollectionChangeRequest.creationRequestForAssetCollection (withTitle: String) method:
var placeholder: PHObjectPlaceholder? PHPhotoLibrary.shared().performChanges({ let request = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumTitle) placeholder = request.placeholderForCreatedAssetCollection }, completionHandler: { (success, error) -> Void in if success { if let id = placeholder?.localIdentifier { let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [id], options: nil) if let album = fetchResult.firstObject {
PHObjectPlaceholder is a
PHObject descendant that is essentially a proxy of a real object that was created (in our case, an album). It is needed in order to get the ID of the created object.
Listing PHAsset
So, we got an album (or rather
PHAssetCollection ), which stores
PHAsset objects. We can get all
PHAsset as follows:
let options = PHFetchOptions() options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: ascending)] let assets: PHFetchResult<PHAsset> = PHAsset.fetchAssets(in: album, options: options)
The assets variable will store the
PHAsset list sorted in ascending photo creation date. We can get a concrete
PHAsset , for example, like this:
if assets.count > 0 { let firstAsset = assets[0] }
Getting a UIImage
To upload an image for a specific
PHAsset, we need the
PHImageManager class:
PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: options) { (image, _) -> Void in // }
Saving image
In order to save the image, you need to create a request using the
PHAssetChangeRequest.creationRequestForAsset method
(from image: UIImage) :
PHPhotoLibrary.shared().performChanges({ let assetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image) let albumChangeRequest = PHAssetCollectionChangeRequest(for: album, assets: assets) if let assetPlaceholder = assetRequest.placeholderForCreatedAsset { let assetPlaceholders: NSArray = [assetPlaceholder] albumChangeRequest?.addAssets(assetPlaceholders) } }, completionHandler: nil)
Remove PHAsset
So we got to the most difficult. To remove
PHAsset, we need the
PHAssetChangeRequest.deleteAssets (_ assets: NSFastEnumeration) method :
PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.deleteAssets(assets as NSFastEnumeration) }, completionHandler: nil)
Conclusion
I described the basic features of the framework. In the future, I will write articles on its other features. All that is not clear - ask in the comments. Any criticism is welcome.
useful links
»
Photos framework reference | Apple»
The Photos Framework | objc.io