• iOS--app自定义相册--创建相簿,存储图片到手机


    我们在APP中点击照片,都会显示出大图,然后在大图的上面会有个保存照片的按钮,照片直接保存到了系统的相册中,但是因为公司产品的需要,让你创建和APP同名的相册保存在里面,那么就对了,可以看下具体的代码和思路,然后把代码直接拿过去就可以用了,对,没错,站在巨人的肩膀上编程

    一共有两种方法自定义相册
    第一种是iOS9之后过期的 <AssetsLibrary/AssetsLibrary.h>苹果原生框架
    第二种是iOS8推出的<Photos/Photos.h> 苹果原生框架,功能更多,但是只支持iOS8之后的版本
    一般推荐使用<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
    {
    //    /**
    //     *  保存到相册的方法
    //     *  @param image#>              需要保存的图片
    //     *  @param completionTarget#>   哪个控制器 description#>
    //     *  @param completionSelector#> 哪个方法 点击方法文档里面有提示 description#>
    //     *  @param contextInfo#>        参数,传什么现实什么 description#>
    //     *  @return
    //     */
        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:

    需要用到<AssetsLibrary/AssetsLibrary.h>这个库


    官方文档给出的提示
    //自定相册的类
    #import <AssetsLibrary/AssetsLibrary.h>
    
    static NSString *kGroupNameKey = @"nameKey";
    static NSString *kDefaultGroupName = @"会跳舞的狮子";
    /** 懒加载 只创建一次library对象 */
    - (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/Photos.h> 这个库
    先简单的介绍下,然后再上代码

    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];


    定义专属相册
    #import <Photos/Photos.h>
    // 在interface中写方法的声明,是为了点语法有智能提示
    - (PHFetchResult<PHAsset *> *)createdAssets;
    - (PHAssetCollection *)createdCollection;
    
    
    
    /**
     *  获得刚才添加到【相机胶卷】中的图片
     */
    - (PHFetchResult<PHAsset *> *)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 *)kCFBundleNameKey];
    
        // 获得所有的自定义相册
        PHFetchResult<PHAssetCollection *> *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<PHAsset *> *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 {
        /*
         requestAuthorization方法的功能
         1.如果用户还没有做过选择,这个方法就会弹框让用户做出选择
         1> 用户做出选择以后才会回调block
    
         2.如果用户之前已经做过选择,这个方法就不会再弹框,直接回调block,传递现在的授权状态给block
         */
    
        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;
                }
            });
        }];
  • 相关阅读:
    DGA域名可以是色情网站域名
    使用cloudflare加速你的网站隐藏你的网站IP
    167. Two Sum II
    leetcode 563. Binary Tree Tilt
    python 多线程
    leetcode 404. Sum of Left Leaves
    leetcode 100. Same Tree
    leetcode 383. Ransom Note
    leetcode 122. Best Time to Buy and Sell Stock II
    天津Uber优步司机奖励政策(12月28日到12月29日)
  • 原文地址:https://www.cnblogs.com/LifeTechnologySupporter/p/6343880.html
Copyright © 2020-2023  润新知