iOS保存图片到相册

在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下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容