iOS开发-自定义专属相册

一共有两种方法自定义相册
第一种是iOS9之后过期的 <</span>AssetsLibrary/AssetsLibrary.h>苹果原生框架
第二种是iOS8推出的 <</span>Photos/Photos.h> 苹果原生框架,功能更多,但是只支持iOS8之后的版本
一般推荐使用 <</span>Photos/Photos.h> ,因为现在版本快iOS10了,有些版本没有升级的用户已经可以抛弃了
1. 添加图片到【相机胶卷】
1 > UIImageWriteToSavedPhotosAlbum函数
2 > AssetsLibrary框架
3 > Photos框架(推荐)

2. 拥有一个【自定义相册】
1 > AssetsLibrary框架
2 > Photos框架(推荐)

3. 将刚才添加到【相机胶卷】的图片,引用(添加)到【自定义相册】
1 > AssetsLibrary框架
2 > Photos框架(推荐)

One:

如果只需要将要将图片保存到系统的相册中,只需要下面两句代码就搞定了

#文档里已经说明这个方法是保存到用户的相机胶卷里面的
Adds the specified image to the user’s Camera Roll album.
- ( void )saveBtns
{
//
UIImageWriteToSavedPhotosAlbum ( self .imageView .image , self ,
@selector (image:didFinishSavingWithError:contextInfo:), @"传什么下面就调用什么什么" );
}

// 需要实现下面的方法,或者传入三个参数即可
- ( void )image:( UIImage *)image didFinishSavingWithError:( NSError *)error contextInfo:( void *)contextInfo
{
if (error) {
[SVProgressHUD showErrorWithStatus: @"保存失败" ];
} else
{
[SVProgressHUD showSuccessWithStatus: @"保存成功" ];
}
}

#注意: @selector() 方法一定要传入三个参数,不然图片虽然保存进去了,但是会崩了
因为参数越界
实参个数 > 形参个数, 就会出现参数越界
-[ NSInvocation setArgument:atIndex:]: index ( 2 ) out of bounds [- 1 , 1 ] :

Two:

需要用到这个库

iOS开发-自定义专属相册
官方文档给出的提示
//自定相册的类
#import

static NSString *kGroupNameKey = @"nameKey" ;
static NSString *kDefaultGroupName = @"会跳舞的狮子" ;
- (ALAssetsLibrary *)library
{
if (!_library) {
_library = [[ALAssetsLibrary alloc] init];
}

return _library;
}
- ( NSString *)groupName
{
//先从沙盒中取得名字
NSString *groupName = [[ NSUserDefaults standardUserDefaults] stringForKey:kGroupNameKey];
if (groupName == nil ) { //如果沙盒中取不到这个key(文件夹的名字)
groupName = kDefaultGroupName;

//储存名字到沙盒里面
[[ NSUserDefaults standardUserDefaults] setObject:groupName forKey:kGroupNameKey];
//synchronize 立马将上面的key保存到沙盒里面
[[ NSUserDefaults standardUserDefaults]synchronize];
}
return groupName;
}

- ( IBAction )clickSave:( id )sender { //创建自定义相册

//获得文件夹的名字 (调用从沙盒里面取的这个方法)
__block NSString *groupName = [ self groupName];
//self的弱引用
__weakSelf;
//图片库
__ weak ALAssetsLibrary *weakLibrary = self .library ;

//创建自定义的相册
[weakLibrary addAssetsGroupAlbumWithName:groupName resultBlock:^(ALAssetsGroup *group) {
if (group) { //新创建的文件夹
//直接把图片添加到文件夹中
[weakSelf addImageToGroup:group];
} else
{
//遍历相册中的每一个文件
[weakLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
//取出文件夹的名称
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([name isEqualToString:groupName]) { //如果相等,那么就是自己创建的文件夹
//添加图片到文件夹中
[weakSelf addImageToGroup:group];

*stop = YES ; // 将图片添加到了文件夹中就停止遍历
} else if ([name isEqualToString: @"Camera Roll" ])
{
//文件夹被用户强制删除了 (拼接一个空格,就是不同的文件夹的名字)
groupName = [groupName stringByAppendingString: @" " ];

//储存新的名字
[[ NSUserDefaults standardUserDefaults] setObject:groupName forKey:kGroupNameKey];
[[ NSUserDefaults standardUserDefaults]synchronize];

//创建新的文件夹中
[weakLibrary addAssetsGroupAlbumWithName:groupName resultBlock:^(ALAssetsGroup *group) {

//添加图片到文件夹中
[weakSelf addImageToGroup:group];


} failureBlock: nil ];
}
} failureBlock: nil ];
}
} failureBlock: nil ];

}

- ( void )addImageToGroup:(ALAssetsGroup *)group
{
__ weak ALAssetsLibrary *weakLibrary = self .library ;
//需要保存的图片
CGImageRef image = self .imageView .image .CGImage ;

//添加图片到相机胶卷 (因为要先存到全部的相片里面. 在根据对应的assetURL)
[weakLibrary writeImageToSavedPhotosAlbum:image metadata: nil completionBlock:^( NSURL *assetURL, NSError *error) {
// asset就是一张照片
[weakLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
//将照片保存到自定的文件夹中
[group addAsset:asset];
[SVProgressHUD showSuccessWithStatus: @"保存成功" ];

} failureBlock: nil ];

}];

}

Three:

用苹果 iOS 推出 这个库
先简单的介绍下,然后再上代码
Photos框架须知
1. PHAsset : 一个PHAsset对象代表一张图片或者一个视频文件
1 > 负责查询一堆的PHAsset对象

2. PHAssetCollection : 一个PHAssetCollection对象代表一个相册
1 > 负责查询一堆的PHAssetCollection对象

3. PHAssetChangeRequest
1 > 负责执行对PHAsset的【增删改】操作
2 > 这个类只能放在-[PHPhotoLibrary performChanges:completionHandler:] 或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用

4. PHAssetCollectionChangeRequest
1 > 负责执行对PHAssetCollection的【增删改】操作
2 > 这个类只能放在-[PHPhotoLibrary performChanges:completionHandler:] 或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用

错误信息
This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]

解决防范
// Asynchronously 异步执行操作
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
JHLog(@ "保存完毕" )
}];

// Synchronously 同步执行操作
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
[PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
} error:&error];

// 这个方法只适合加载普通的plist文件,不能用来加载Info.plist
[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@ "Test" ofType:@ "plist" ]];


安全提示按钮选择
// PHAuthorizationStatusNotDetermined
// 用户还没有对当前App授权过(用户从未点击过Don't Allow或者OK按钮)

// PHAuthorizationStatusRestricted
// 因为一些系统原因导致无法访问相册(比如家长控制)

// PHAuthorizationStatusDenied
// 用户已经明显拒绝过当前App访问相片数据(用户已经点击过Don't Allow按钮)

// PHAuthorizationStatusAuthorized
// 用户已经允许过当前App访问相片数据(用户已经点击过OK按钮)

# 只有遵守了NSFastEnumeration协议的对象才能使用for-in循环
封装好的代码,可以根据公司的需求进行修改
我创建新的相册的名字就是APP的名字,
// 获取软件的名字作为相册的标题
NSString  title = [NSBundle mainBundle].infoDictionary[(NSString )kCFBundleNameKey];
iOS开发-自定义专属相册
定义专属相册
#import 
// 在interface中写方法的声明,是为了点语法有智能提示
(PHFetchResult *)createdAssets;
(PHAssetCollection *)createdCollection;



(PHFetchResult *)createdAssets
{
    __block  NSString  *createdAssetId  nil ;

    // 添加图片到【相机胶卷】
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        createdAssetId [PHAssetChangeRequest creationRequestForAssetFromImage: self .imageView .image ] .placeholderForCreatedAsset .localIdentifier ;
   error: nil ];

    if  (createdAssetId ==  nil return   nil ;

    // 在保存完毕后取出图片
    return  [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetId] options: nil ];
}

(PHAssetCollection *)createdCollection
{
    // 获取软件的名字作为相册的标题
    NSString  *title [ NSBundle  mainBundle] .infoDictionary [( NSString  *)k CFBundleNameKey ];

    // 获得所有的自定义相册
    PHFetchResult *collections [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options: nil ];
    for  (PHAssetCollection *collection  in  collections) {
        if  ([collection .localizedTitle  isEqualToString:title]) {
            return  collection;
        }
    }

    // 代码执行到这里,说明还没有自定义相册

    __block  NSString  *createdCollectionId  nil ;

    // 创建一个新的相册
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        createdCollectionId [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title] .placeholderForCreatedAssetCollection .localIdentifier ;
   error: nil ];

    if  (createdCollectionId ==  nil return   nil ;

    // 创建完毕后再取出相册
    return  [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCollectionId] options: nil ] .firstObject ;
}

( void )saveImageIntoAlbum
{
    // 获得相片
    PHFetchResult *createdAssets  self .createdAssets ;

    // 获得相册
    PHAssetCollection *createdCollection  self .createdCollection ;

    if  (createdAssets ==  nil  || createdCollection ==  nil {
        [SVProgressHUD showErrorWithStatus: @"保存失败!" ];
        return ;
    }

    // 将相片添加到相册
    NSError  *error  nil ;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        PHAssetCollectionChangeRequest *request [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdCollection];
        [request insertAssets:createdAssets atIndexes:[ NSIndexSet  indexSetWithIndex: 0 ]];
   error:&error];

    // 保存结果
    if  (error) {
        [SVProgressHUD showErrorWithStatus: @"保存失败!" ];
    else  {
        [SVProgressHUD showSuccessWithStatus: @"保存成功!" ];
    }
}

( IBAction )save {
   

    PHAuthorizationStatus oldStatus [PHPhotoLibrary authorizationStatus];

    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        dispatch_async (dispatch_get_main_queue(), ^{
            switch  (status) {
                case  PHAuthorizationStatusAuthorized: {
                    //  保存图片到相册
                    [ self  saveImageIntoAlbum];
                    break ;
                }

                case  PHAuthorizationStatusDenied: {
                    if  (oldStatus == PHAuthorizationStatusNotDetermined)  return ;

                    JHLog( @"提醒用户打开相册的访问开关" )
                    break ;
                }

                case  PHAuthorizationStatusRestricted: {
                    [SVProgressHUD showErrorWithStatus: @"因系统原因,无法访问相册!" ];
                    break ;
                }

                default :
                    break ;
            }
        });
    }];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值