因为iOS系统相册权限及照片显示的问题,所以没法像android一样直接在某个路径下创建文件夹存储照片,并利用名字来取照片。iOS实现存储照片到自定义相册,其实是先把图片存到系统相册,然后创建一个相薄,在从系统相册中取出那张照片添加到自定义的相薄中。
使用框架
1.AssetsLibrary,这个框架在iOS9之后废弃掉了,所以建议大家用第二种方法
2.Photos,这个从iOS8之后就可以使用,取代了AssetsLibrary
框架中的类与参数介绍
· PHAssetCollection 图片的集合,其实就是指的一个相册,不管是系统的还是自定义的
· PHFetchResult 表示该相册中的资源的集合
· PHAsset 表示这个相册中的某一个资源,可以是图片或者视频,上面的PHFetchResult其实就相当于一个数组,而PHAsset就相当于数组中的子元素
· localIdentifier PHObject中的一个参数,某个对象的唯一标识符,想要找到相册中存取的某张照片,可以通过这个id遍历查找,其实就像手机的UDID,唯一标识你这个手机
代码块
保存照片到自定义相册
//MARK: -将图片保存到自定义相册中
-(void)saveImageToCustomAblum
{
//将图片保存到系统的相册
PHFetchResult<PHAsset *> *assets = [self saveImageWithPhotos];
if (assets == nil)
{
//自已封装一个debug模式下的log,不然到时候上线还要注释掉
DLog(@"保存失败");
return;
}
//创建自定义相册(自己命名,如果没有则创建)
PHAssetCollection *assetCollection = [self getAssetCollectionAppNameAndCreate];
if (assetCollection == nil) {
DLog(@"相册创建失败");
return;
}
//将刚才保存到系统相册的图片添加到自定义相册中
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//选取自定义相册进行操作
PHAssetCollectionChangeRequest *collectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//插入图片到自定义相册
PHFetchResult<PHAsset *> *assetCount = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
[collectionChangeRequest insertAssets:assets atIndexes:[NSIndexSet indexSetWithIndex:assetCount.count]];
//取出保存的那个对象(图片)
PHAsset *ass = [assets objectAtIndex:0];
NSString *aaa = [ass localIdentifier];
//暂存一下图片的id,后面需要通过id取出照片(你可以存一个数组,也可以取出多张照片,这里就说一下取出单张的)
[[NSUserDefaults standardUserDefaults] setObject:aaa forKey:kAssetID];
} error:&error];
if (error) {
DLog(@"保存失败");
return;
}
DLog(@"保存成功");
}
1.保存图片到系统的相册中,返回结果是保存成功后的图片集合
-(PHFetchResult<PHAsset *> *)saveImageWithPhotos
{
__block NSString *createdAssetID = nil;
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//获取图片的id
createdAssetID = [PHAssetChangeRequest creationRequestForAssetFromImage:_imm].placeholderForCreatedAsset.localIdentifier;
} error:&error];
if (error) {
return nil;
}
//获取保存到系统相册成功后的 asset 对象集合(一张图片也是返回一个集合)
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetID] options:nil];
return assets;
}
2.判断有没有拥有与你设定的名字同名的自定义相册(如果没有则创建)
-(PHAssetCollection *)getAssetCollectionAppNameAndCreate
{
//设置你想要创建的相册的名字
NSString *title = @"我的新建相册";
//获取与要创建的相册同名的自定义相册
PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collections) {
//遍历
if ([collection.localizedTitle isEqualToString:title]) {
//找到了同名的自定义相册,返回
return collection;
}
}
//程序走到这,说明没有找到自定义的相册,需要创建
NSError *error = nil;
__block NSString *createID = nil; //用来获取创建好的相册
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//发起了创建新相册的请求,并拿到相册的id,当前并没有创建成功,待创建成功后,通过id来获取创建好的自定义相册
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
createID = request.placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
if (error) {
DLog(@"创建失败");
return nil;
}else{
DLog(@"创建成功");
[[NSUserDefaults standardUserDefaults] setObject:createID forKey:kAlbumID];
//通过id获取创建完成的相册
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createID] options:nil].firstObject;
}
}
从相册中取照片
1.先通过你自定义的相册的名字,找到这个PHAssetCollection
2.找到你的PHAssetCollection(自定义相册)之后,通过遍历相册集合,根据id值判断是否有匹配的图片
//通过 相薄名字查找新建相册
var albumColl = PHAssetCollection()
let collections:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: nil)
for j in 0..<collections.count {
let collection:PHAssetCollection = collections[j] as! PHAssetCollection
if collection.localizedTitle == "我的新建相册" {
//找到了同名的自定义相册,返回
albumColl = collection
break
}
}
let picAssets:PHFetchResult = PHAsset.fetchAssetsInAssetCollection(albumColl, options: nil)
//遍历assets集合,找到id值一样的图片取出来
for i in 0..<picAssets.count {
let asset:PHAsset = picAssets[i] as! PHAsset
if asset.localIdentifier == (NSUserDefaults.standardUserDefaults().objectForKey("assetId") as! String)! {
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: { (result: UIImage?, dictionry: Dictionary?) in
//根据result取出这张照片
if result != nil && result != NSNull() {
self.albumIma = result!
} else {
self.albumIma = UIImage.init(named: "pic_loading")!
}
})
}
}
注意
自定义相册里面的照片,其实相当于系统相册中图片的一个影子,系统相册里的图片没了,影子也就不存在了。因为每次拍照存放照片,实际上先存放到系统相册,然后从系统相册插入过去的;再删除照片的时候,系统相册的删除了,两个相册的照片就全没了,但是自定义相册里的照片删除,系统相册的照片则无影响
多说一句,假如你把每次拍照的图片都存放到一个本地文件或者小型的SQL数据库里面,进行持久化存储了,那么一定要在程序每次进入活跃状态的时候,检测自定义相册中的图片和数据库中的是否匹配,不匹配就删除本地多余的照片,这样才能做到实时对应。至于检测匹配就不要用两个for in嵌套了(时间复杂度O(m*n)),通过两个哈希序列进行比较是比较简单的做法(时间复杂度O(m+n))。