不知道你们有没有这样的侥幸心理:Apple更新了新的框架API,旧的虽然被标为废弃了但还是能用,就一直用着旧的偷懒不去改最新的。有句话说得好:不是不报,时候未到。我最近遇到了要报的懒。
在iOS里,保存图片到相册有一个简单的UIImage
的方法:
UIImageWriteToSavedPhotosAlbum(_image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
然后需要实现上面SEL里的回调,一个系统的方法:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
}
当然这个只能简单的保存图片到默认的系统相册中,如果要创建自己的相册,就需要用ALAssetsLibrary
框架:
// 先保存图片
- (void)saveImage:(UIImage*)image toAlbum:(NSString *)albumName{
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc]init];
[assetsLibrary writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)image.imageOrientation completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"Save image fail:%@",error);
}else{
NSLog(@"Save image succeed.");
[self addAssetURL:assetURL toAlbum:albumName withAssestLibrary:assetsLibrary completionBlock:(SaveRecordCompletion)completionBlock failBlock:(void(^)(NSError *error))failBlock] ;
}
}];
// 再添加到指定相册
-(void)addAssetURL:(NSURL*)assetURL toAlbum:(NSString*)albumName withAssestLibrary:(ALAssetsLibrary *)assetsLibrary completionBlock:(SaveRecordCompletion)completionBlock failBlock:(void(^)(NSError *error))failBlock
{
__block BOOL albumWasFound = NO;
//遍历所有的相册
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
//compare the names of the albums
if ([albumName compare: [group valueForProperty:ALAssetsGroupPropertyName]] == NSOrderedSame)
{
//找到名字为albumName的相册
albumWasFound = YES;
//get a hold of the photo's asset instance
[assetsLibrary assetForURL: assetURL resultBlock:^(ALAsset *asset) {
//add photo to the target album
//NSAssert(asset != nil, @"asset不能为空");
[group addAsset: asset];
} failureBlock: nil];
*stop = YES;
}
if (group==nil && albumWasFound==NO)
{
__weak ALAssetsLibrary* weakAssetsLibrary = assetsLibrary;
[self addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *group) {
[weakAssetsLibrary assetForURL: assetURL resultBlock:^(ALAsset *asset)
{
NSAssert(asset != nil, @"asset不能为空");
//add photo to the newly created album
[group addAsset: asset];
} failureBlock: nil];
} failureBlock: nil];
*stop = YES;
}
} failureBlock:failBlock];
}
因为ALAssetsLibrary的API在iOS9之后被标位弃用了,所以会有出错的风险。我遇到的问题是,当开启使用iCloud图库时,图片只会保存在系统默认的相册下,保存不到我们应用的相册下,关闭iCloud时就不会有这种问题(在iOS10、11下出现的)。所以怀疑到应该是在开启iCloud时,苹果做了一些操作导致旧的框架不支持了。
下面主要看下在iOS8后出现的Photos
框架的简单使用。
首先,我们可以创建一个helpe
类,用来单独做对相册的操作(比如我的叫SRHPhotoHelper
,当然你可以按照自己的想法随意写)。
直接上代码:
+ (void)srh_saveImage:(UIImage *)image completionHandle:(void (^)(NSError *, NSString *))completionHandler {
// 1. 获取照片库对象
PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
// 假如外面需要这个 localIdentifier ,可以通过block传出去
__block NSString *localIdentifier = @"";
// 2. 调用changeblock
[library performChanges:^{
// 2.1 创建一个相册变动请求
PHAssetCollectionChangeRequest *collectionRequest = [self getCurrentPhotoCollectionWithAlbumName:SRHAlbumName];
// 2.2 根据传入的照片,创建照片变动请求
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
// 2.3 创建一个占位对象
PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset];
localIdentifier = placeholder.localIdentifier;
// 2.4 将占位对象添加到相册请求中
[collectionRequest addAssets:@[placeholder]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (error) {
[iConsole log:@"保存照片出错>>>%@", [error description]];
completionHandler(error, nil);
} else {
completionHandler(nil, localIdentifier);
}
}];
}
+ (PHAssetCollectionChangeRequest *)getCurrentPhotoCollectionWithAlbumName:(NSString *)albumName {
// 1. 创建搜索集合
PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 2. 遍历搜索集合并取出对应的相册,返回当前的相册changeRequest
for (PHAssetCollection *assetCollection in result) {
if ([assetCollection.localizedTitle containsString:albumName]) {
PHAssetCollectionChangeRequest *collectionRuquest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
return collectionRuquest;
}
}
// 3. 如果不存在,创建一个名字为albumName的相册changeRequest
PHAssetCollectionChangeRequest *collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
return collectionRequest;
}
具体的讲解可以自己去查API或者看一下这篇文章、这篇文章。后续我会把取相册图片、视频的代码分享出来,包括完整的demo。