先上最终效果图:
使用前需要添加该框架,并且在文件头部 import photos
PhotosFramework
首先我们先了解一下PhotosFramework
Work with image and video assets managed by the Photos app, including those from iCloud Photo Library and Live Photos. Fetch and cache full-sized assets or thumbnails asynchronously, revise content, and sync revisions to multiple devices.
处理图像和视频资源,包括iCloud上的网络资源和本地资源。异步获取和缓存资源,保存资源修改,并且将修改同步到所有的设备中。
在这个项目中,我们只需要获取本地资源,并且展示出来。并没有涉及到iCloud和修改资源。
- PHPhotoLibrary -- 管理照片库访问和更改的共享对象
-
用来获取相册的授权情况和请求授权
let authorizationStatus = PHPhotoLibrary.authorizationStatus() switch authorizationStatus { case .authorized: print("已经授权") return true case .notDetermined: print("不确定是否授权") //一般是第一次打开app时的状态 // 请求授权 PHPhotoLibrary.requestAuthorization({ (status) in }) case .denied: print("拒绝授权") case .restricted: print("限制授权") break }
- 对照片库进行更改或者是监听相册更改情况。前者应用一般是保存图片、视频等资源到系统相册中(这方面先不深入讨论)。
-
PHAsset 图片、视频等,我们在图片库中最终拿到的某一资源的对象,然后将该对象转换成UIImage,展示出来
func getImageWithAsset(_ asset: PHAsset, size targetSize: CGSize, finishedCallack: @escaping (_ image: UIImage) -> ()) { let options = PHImageRequestOptions() options.resizeMode = .exact // 返回图像与目标size保持一致 options.deliveryMode = .highQualityFormat // 只返回高像素的图像 var size = targetSize // 如果没有目标大小,则返回原图 if targetSize == .zero { size = CGSize(width: asset.pixelWidth, height: asset.pixelHeight) } PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .default, options: options) { (image, info) in // 如果是image是nil 则直接返回 guard let image = image else { return } // 拿到图片,则返回 finishedCallack(image) } }
上面的PHImageRequestOptions是用来设置请求图片的相关属性的。
options.resizeMode 表示:如果资源是压缩图片时,系统对图片解码时会参照targetSize的值。
PHImageRequestOptions
.fast 返回的图片可能会比targetSize大
.exact 则与targetSize保持一致。
options.deliveryMode 有以下取值:
.opportunistic 会返回一张小图和大图
.highQualityFormat 只返回大图
.fastFormat 只返回小图
-
PHAssetCollection 表示PHAsset的集合,包括系统相册,用户创建的相册等。以下是获取智能相册的代码:
func getSmartAlbums() -> [AlbumItem]? { //获取所有的智能相册 let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil) print("智能相册有\(smartAlbums.count)个") let options = PHFetchOptions() options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: true)] let albumsArray = getAssetResultInCollection(smartAlbums, fetchOptions: options) return albumsArray } func getAssetResultInCollection(_ collection: PHFetchResult<PHAssetCollection>, fetchOptions options: PHFetchOptions) ->[AlbumItem]? { var albumsArray = [AlbumItem]() for index in 0..<collection.count { //获取一个相册 let assetCollection = collection[index]; //然后从每一个智能相册中获取资源,获取到的是一个list let assetFecthResults = PHAsset.fetchAssets(in: assetCollection, options: nil); print("\(assetCollection.localizedTitle!)相册,共有照片数:\(assetFecthResults.count)") if assetFecthResults.count > 0 { //有照片的相册 let album = AlbumItem.init(title: assetCollection.localizedTitle, fetchResult: assetFecthResults) albumsArray.append(album) } } return albumsArray }
由此可见:smartAlbums是PHAssetCollection,是所有智能相册的集合,而该集合里面的元素assetCollection(表示的是某个智能相册)也是PHAssetCollection,包含的PHAsset就是一张照片。
PHCollection 抽象类,PHAssetCollection 和 PHCollectionList的父类,表示PHAsset的集合或者自身的集合。
PHCollectionList 表示照片库里面的文件夹,是PHAsset 和自身对象的集合。
-
PHFetchResult 表示有序的图片和图片集合的列表,smartAlbums 的具体类型应该是PHFetchResult<PHAssetCollection>, 意思是列表内的元素是PHAssetCollection,一般是用fetch method获取得到的结果。
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
-
PHFetchOptions 使用fetch method时对结果进行管理的选项,譬如:排序条件,资源类型,是否收藏等。下面是以创建时间升序排序:
let options = PHFetchOptions() options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: true)]
-
PHImageManager 提供获取图片UIImage对象、视频PlayerItem对象等方法。如果资源需要在界面上展示出来,需要使用该对象获取。
例如从PHAsset中获取图片:PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .default, options: options) { (image, info) in // 如果是image是nil 则直接返回 guard let image = image else { return } // 拿到图片,则返回 finishedCallack(image) }