iOS保存图片到相册

作者: 翀鹰精灵 | 来源:发表于2018-08-13 11:22 被阅读3273次

    在APP中点击照片,都会显示出大图,然后在大图的上面会有个保存照片的按钮,照片直接保存到了系统的【相机胶卷】相册中,但是因为公司产品的需要,我们需要创建和APP同名的相册保存在【自定义相册】里面,这也就是分应用存储,因为用户可能从QQ,微信,微博分别存储,下次用户想找某个应用的图片,直接点开该应用相册即可,提高用户体验。
    注意:
    【自定义相册】里面的图片来源于【相机胶卷】相册中,即:【相机胶卷】引用【自定义相册】, 如果用户删掉【相机胶卷】里面的图片, 那么【自定义相册】重的图片也会删掉。但是,如果用户删掉【自定义相册】里面的图片, 那么【相机胶卷】中依然有该图片。

    开发步骤:
    • 1.先保存图片到【相机胶卷】(不能直接保存到自定义相册中)
    • 2.拥有一个【自定义相册】
    • 3.将刚才保存到【相机胶卷】里面的图片引用到【自定义相册】

    方法1:用C语言函数实现

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

    //参数1:图片对象
    //参数2:成功方法绑定的target
    //参数3:成功后调用方法
    //参数4:需要传递信息(成功后调用方法的参数)
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    #pragma mark -- <保存到相册>
    -(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
        NSString *msg = nil ;
        if(error){
            msg = @"保存图片失败" ;
        }else{
            msg = @"保存图片成功" ;
        }
    }
    
    

    注意:UIImageWriteToSavedPhotosAlbum方法必须实现图1的代理方法,否则会崩溃。

    1.png

    界面效果如下:界面图


    效果图.png
    方法2:使用Photos框架实现
    2.1 Photos01-基本认识

    PHAsset : 一个PHAsset对象就代表相册中的一张图片或者一个视频
    PHAssetCollection : 一个PHAssetCollection 对象就代表一个相册

    如果我们想保存图片到【相机胶卷】,首先要保证添加一个新的PHAsset对象,那么如何操作这些对象呢?无非是对这些对象进行增删改查。

    PHAsset 一个PHAsset对象就代表相册中的一张图片或者一个视频
    增删改 PHAssetChangeRequest 包括图片/视频相关的改动操作

    [PHAsset fetchAssets...];

    PHAssetCollection 一个PHAssetCollection 对象就代表一个相册

    增删改 PHAssetCollectionChangeRequest 包括相册相关的所有改动操作

    [PHAssetCollection fetchAssetCollectionsContainingAsset:...];

    2.2 Photos02-保存图片到相机胶卷
        //保存图片到【相机胶卷】
        /// 异步执行修改操作
        [[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
            [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (error) {
                NSLog(@"%@",@"保存失败");
            } else {
                NSLog(@"%@",@"保存成功");
            }
        }];
    

    效果如图2 图3所示


    2.png 3.png

    Tips:
    如果直接使用 [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image]; 则会出现如下的崩溃信息

    reason: 'This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
    

    结论:凡是涉及增删改的操作,均需要放在performChanges里面执行。

     [[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
           // 这里执行操作
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
        }];
    
    2.3 Photos03-创建新的相册
        NSError *error = nil;
        [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
            //获取app名字
            
            NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
            //创建一个【自定义相册】
            [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
        } error:&error];
    

    效果如图4:


    4.png

    Tips:如果我们一直点击保存图片按钮,则会出现重复创建多个相册的问题:

    如图5所示

    5.png

    接着我们来解决这个问题。

    2.4 Photos04-查询相册
        NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
        //查询所有【自定义相册】
        PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        PHAssetCollection *createCollection = nil;
        for (PHAssetCollection *collection in collections) {
            if ([collection.localizedTitle isEqualToString:title]) {
                createCollection = collection;
                break;
            }
        }
        if (createCollection == nil) {
            //当前对应的app相册没有被创建
            //创建一个【自定义相册】
            NSError *error = nil;
            [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
                //创建一个【自定义相册】
                [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
            } error:&error];
    
        }
    

    输出结果:
    此时,无论你点击多少次,均只会创建一个与APP同名的相册。

    Tips: 如果我们想把图片保存到【自定义相册】里面的话,必须拿到相册对象,但是细心地你此时可能会发现,如果是第一次创建相册(即:相册中没有与APP同名的相册),createCollection对象会为nil,所以我们还需要优化创建【自定义相册】的代码。

    核心代码:

        if (createCollection == nil) {
            //当前对应的app相册没有被创建
            //创建一个【自定义相册】
            NSError *error = nil;
            __block NSString *createCollectionID = nil;
            [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
                //创建一个【自定义相册】
               createCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
            } error:&error];
            createCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createCollectionID] options:nil].firstObject;
        }
        NSLog(@"%@",createCollection);
    

    输出结果:

    2018-08-12 12:31:59.198751+0800 SavePhotoDemo[971:36240] <PHAssetCollection: 0x7fde6dc33960> 7C7FBA58-54AA-4320-9B2A-593BB75428FB/L0/040, title:"SavePhotoDemo", subtitle:"(null)" assetCollectionType=1/2
    
    2.5 Photos05-保存图片到自定义相册

    我们创建完相册之后,需要将【相机胶卷】中的图片放到【自定义相册】里面去。
    核心代码如下:

        // 1.先保存图片到【相机胶卷】
        /// 同步执行修改操作
        NSError *error = nil;
        __block PHObjectPlaceholder *placeholder = nil;
        [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
           placeholder =  [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset;
        } error:&error];
        if (error) {
            NSLog(@"保存失败");
            return;
        }
        // 2.拥有一个【自定义相册】
        PHAssetCollection * assetCollection = self.createCollection;
        if (assetCollection == nil) {
            NSLog(@"创建相册失败");
        }
        // 3.将刚才保存到【相机胶卷】里面的图片引用到【自定义相册】
        [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
            PHAssetCollectionChangeRequest *requtes = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
            [requtes addAssets:@[placeholder]];
        } error:&error];
        if (error) {
            NSLog(@"保存图片失败");
        } else {
            NSLog(@"保存图片成功");
        }
    

    此时,我们点击保存图片到新建相册~按钮的时候,改图片变被保存到【相机胶卷】和【自定义相册】里面了。
    如图6所示

    6.png

    但是,此时你会发现,每保存新的图片,自定义相册中均会添加到后面,那么如何把每次新添加的图片前置呢?我们发现【相机胶卷】中每次新的图片均会作为封面,系统自带的这个比较智能,如图图7所示


    7.png

    所以修改添加图片到相册的代码

        // 3.将刚才保存到【相机胶卷】里面的图片引用到【自定义相册】
        [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
            PHAssetCollectionChangeRequest *requtes = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
            [requtes insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
        } error:&error];
        
    

    此时,【自定义相册】中新添加的图片便会作为相册的封面了,效果如图8所示。

    8.png

    Demo下载

    相关文章

      网友评论

        本文标题:iOS保存图片到相册

        本文链接:https://www.haomeiwen.com/subject/srmybftx.html