📜 ⬆️ ⬇️

iOS: work with the gallery (Photos framework)

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

Source: https://habr.com/ru/post/318810/


All Articles