前言:
相册保存到系统相册中,通常有三种办法:
- UIImageWriteToSavedPhotosAlbum() 方法保存
- 是使用 Photos 框架来实现。
- ALAssetsLibrary 在iOS9.0之后就被标记为过时方法,苹果建议使用Photos框架代替
问:UIImageWriteToSavedPhotosAlbum()保存图片很简单,但为什么还要用Photos?
答:
1、Photos可以为相册相片做标识,方便保存后取出它们
2、Photos有同步操作,可以同时保存多张图片
3、可以存储到特定的相册
···(有其他优点,朋友们可以拍砖评论)
Photos框架功能十分强大,不止保存功能
下面详解Photos这个iOS8.0才出现的新框架:
对 PhotoKit 基本构成的介绍:(本文采取最新的swift版本,OC得慢慢过渡到swift了)
PHAsset
: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源
PHFetchOptions
: 获取资源时的参数,可以传 nil,即使用系统默认值
PHAssetCollection
: PHCollection 的子类,表示一个相册或者一个时刻,或者是一个「智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等,如下图所示)
PHFetchResult
: 表示一系列的资源结果集合,也可以是相册的集合,从PHCollection 的类方法中获得
PHImageManager
:用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格
PHImageRequestOptions
:如上面所说,控制加载图片时的一系列参数
PHPhotoLibrary
:表示由照片应用程序管理的整套资源和集合,包括存储在本地设备上和(允许情况下)存储在iCloud照片中的资源。您可以使用此对象对照片库中的对象集执行更改,例如,编辑资源元数据或内容,插入新资源或重新排列集合的成员,您还可以使用照片库对象来注册照片在内容或资源元数据和集合发生变化时发送的消息,并验证用户是否已授权您的应用访问照片内容(对PHPhotoLibrary
的描述在文章末尾)
一、保存照片
1、UIImageWriteToSavedPhotosAlbum()保存照片
let image = self.imageView.image!
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
2、Photos保存照片
保存照片到相册
func savePhoto(image: UIImage) {
PHPhotoLibrary.shared().performChanges({
// Request creating an asset from the image.
let creationRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceholder = creationRequest.placeholderForCreatedAsset
//保存标志符
self.localId = assetPlaceholder?.localIdentifier
}, completionHandler: { success, error in
if !success { print("error creating asset: \(error)") }
else {
print("成功了")
//通过标志符获取对应的资源
let assetResult = PHAsset.fetchAssets(
withLocalIdentifiers: [self.localId], options: nil)
let asset = assetResult[0]
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData)
-> Bool in
return true
}
//获取保存的图片路径
asset.requestContentEditingInput(with: options, completionHandler: {
(contentEditingInput:PHContentEditingInput?, info: [AnyHashable : Any]) in
print("地址:",contentEditingInput!.fullSizeImageURL!)
})
}
})
}
保存照片到特定相册
func savePhoto(image: UIImage, album: PHAssetCollection) {
PHPhotoLibrary.shared().performChanges({
// Request creating an asset from the image.
let creationRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
// // Request editing the album.
guard let addAssetRequest = PHAssetCollectionChangeRequest(for: album) else { return }
let assetPlaceholder = creationRequest.placeholderForCreatedAsset
//保存标志符
self.localId = assetPlaceholder?.localIdentifier
// Get a placeholder for the new asset and add it to the album editing request.
addAssetRequest.addAssets([creationRequest.placeholderForCreatedAsset!] as NSArray)
}, completionHandler: { success, error in
if !success
{
print("error creating asset: \(error)")
}
else {
print("添加到自定义相册成功了")
}
})
}
二、创建自定义相册
func createAssetCollection() -> Void{
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: "我是韦德")
}) { (isSuccess: Bool, error) in
if !isSuccess { print("error creating assetCollection: \(error)") }
else {print("成功了")}
//use the PHObjectPlaceholder object provided by the change request. After the change block completes, use the placeholder object’s localIdentifier property to fetch the created object.
}
}
note:可以使用PHObjectPlaceholder
为相册坐标识,然后在改变完成后(change block completes),获取刚才创建的相册
三、获取相册
从PHAssetCollection 获取中获取到的可以是相册也可以是资源,但无论是哪种内容,都统一使PHFetchResult 对象封装起来,因此虽然 PHAssetCollection 获取到的结果可能是多样的,但通过PHFetchResult 就可以使用统一的方法去处理这些内容(即遍历 PHFetchResult)
1、列出所有相册智能相册
func getAlbum() {
let smartAlbums: PHFetchResult = PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.smartAlbum, subtype: PHAssetCollectionSubtype.albumRegular, options: nil)
print("智能\(smartAlbums.count)个")
// 这时 smartAlbums 中保存的应该是各个智能相册对应的 PHAssetCollection
for index in 0..
2、列出用户创建的相册,并获取每一个相册中的PHAsset对象
func fetchAllUserCreatedAlbum() {
//获取自定义的相册
let topLevelUserCollections:PHFetchResult = PHCollectionList.fetchTopLevelUserCollections(with: nil)
//topLevelUserCollections中保存的是各个用户创建的相册对应的PHAssetCollection
print("用户创建\(topLevelUserCollections.count)个")
for i in 0..
3、获取所有资源的集合,并按资源的创建时间排序
func getAllSourceCollection() -> Array{
let options:PHFetchOptions = PHFetchOptions.init()
var assetArr = [PHAsset]()
options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: true)]
let assetFetchResults:PHFetchResult = PHAsset.fetchAssets(with: options)
for i in 0..
4、获取缩略图方法
func getAssetThumbnail(asset:PHAsset) -> Void {
//获取缩略图
let manager = PHImageManager.default()
let option = PHImageRequestOptions() //可以设置图像的质量、版本、也会有参数控制图像的裁剪
//返回一个单一结果,返回前会堵塞线程,默认是false
option.isSynchronous = true
manager.requestImage(for: asset, targetSize: CGSize.init(width: 100, height: 200), contentMode: .aspectFit, options: option) { (thumbnailImage, info) in
print("缩略图:\(thumbnailImage),图像信息:\(info)")
self.imageView.image = thumbnailImage;
}
}
5、获取原图的方法
func getAssetOrigin(asset:PHAsset) -> Void {
//获取原图
let manager = PHImageManager.default()
let option = PHImageRequestOptions() //可以设置图像的质量、版本、也会有参数控制图像的裁剪
option.isSynchronous = true
manager.requestImage(for: asset, targetSize:PHImageManagerMaximumSize, contentMode: .aspectFit, options: option) { (originImage, info) in
self.imageView.image = originImage;
print("原图:\(originImage),图像信息:\(info)")
}
}
PHPhotoLibrary扩展:
class func authorizationStatus()```
返回是否可以进入相册的授权信息
Returns information about your app’s authorization for accessing the user’s Photos library.
将```NSPhotoLibraryUsageDescription``` key 加入Info.plist
如果用户不允许,则会返回```notDetermined```,从而可以调用```requestAuthorization(_:)```
class func requestAuthorization((PHAuthorizationStatus) -> Void)```
请求用户的权限,用于访问照片库。
class func shared()```
获取共享照片库对象。
func performChanges(() -> Void, completionHandler: ((Bool, Error?) -> Void)? = nil)```
异步修改照片库
func performChangesAndWait(() -> Void)```
同步修改照片库
func register(PHPhotoLibraryChangeObserver)```
注册一个对象来监听照片库是否改变
Registers an object to receive messages when objects in the photo library change.
func unregisterChangeObserver(PHPhotoLibraryChangeObserver)```
移除注册,不再接收改变消息
Unregisters an object so that it no longer receives change messages.
本文部分参考[API Reference](https://developer.apple.com/reference/photos)
[代码链接](https://github.com/DWadeIsTheBest/PhotosDemo)