zoukankan      html  css  js  c++  java
  • ios开发多选照片实现

    #import "ViewController.h"
    #import <Photos/Photos.h>
    
    @interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (IBAction)selectImage {
        [self getThumbnailImages];
    }
    
    /**
     *  获得所有相簿的原图
     */
    - (void)getOriginalImages
    {
        // 获得所有的自定义相簿
        PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        // 遍历所有的自定义相簿
        for (PHAssetCollection *assetCollection in assetCollections) {
            [self enumerateAssetsInAssetCollection:assetCollection original:YES];
        }
        
        // 获得相机胶卷
        PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
        [self enumerateAssetsInAssetCollection:cameraRoll original:YES];
    }
    
    /**
     *  获得所有相簿中的缩略图
     */
    - (void)getThumbnailImages
    {
        // 获得所有的自定义相簿
        PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        // 遍历所有的自定义相簿
        for (PHAssetCollection *assetCollection in assetCollections) {
            [self enumerateAssetsInAssetCollection:assetCollection original:NO];
        }
        
        // 获得相机胶卷
        PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
        [self enumerateAssetsInAssetCollection:cameraRoll original:NO];
    }
    
    /**
     *  遍历相簿中的所有图片
     *
     *  @param assetCollection 相簿
     *  @param original        是否要原图
     */
    - (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollection original:(BOOL)original
    {
        NSLog(@"相簿名:%@", assetCollection.localizedTitle);
        
        PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
        // 同步获得图片, 只会返回1张图片
        options.synchronous = YES;
    
        // 获得某个相簿中的所有PHAsset对象
        PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
        for (PHAsset *asset in assets) {
            // 是否要原图
            CGSize size = original ? CGSizeMake(asset.pixelWidth, asset.pixelHeight) : CGSizeZero;
            
            // 从asset中获得图片
            [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                NSLog(@"%@", result);
            }];
        }
    }
    
    /**
     *  获得相机胶卷中的所有图片
     */
    - (void)getImagesFromCameraRoll
    {
        // 获得相机胶卷中的所有图片
        PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithOptions:nil];
        
        __block int count = 0;
        
        for (PHAsset *asset in assets) {
            [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(asset.pixelWidth, asset.pixelHeight) contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                NSLog(@"%@ - %zd", result, count++);
            }];
        }
    }
    
    /**
     *  利用UIImagePickerController挑选图片
     */
    - (void)getImageFromIpc
    {
        // UIImagePickerController : 可以从系统自带的App(照片相机)中获得图片
    
        // 判断相册是否可以打开
        if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
    
        UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
        // 打开照片应用(显示所有相簿)
        ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        // 打开照片应用(只显示"时刻"这个相簿)
        // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        // 照相机
        // ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
        ipc.delegate = self;
        [self presentViewController:ipc animated:YES completion:nil];
    }
    
    #pragma mark - <UIImagePickerControllerDelegate>
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
    {
        // 销毁控制器
        [picker dismissViewControllerAnimated:YES completion:nil];
    
        // 设置图片
        self.imageView.image = info[UIImagePickerControllerOriginalImage];
    }
    
    @end

    总结:1:从相册中选取照片可以利用UIImagePickerController,前提是必须遵守两个协议:

    <UIImagePickerControllerDelegate, UINavigationControllerDelegate>但是此种方法只能获取到相册中的一张照片。使用方法如下:1:可以先判断其是否支持相机或是相册,不支持直接return,不执行以下代码 2:创建对象,设置代理,在设置sourceType(注意两种类型的区别),弹出就用presentViewController可以弹出相册,dissmiss返回到应用。实现代理方法获取图片:   self.imageView.image = info[UIImagePickerControllerOriginalImage];3:UIImagePickerController显示中文界面:

    1.Project-->Info-->Localizations添加Chinese

    2.修改Target-->Info-->Localization native development region : China 

    - (void)getImageFromIpc

    {

        // UIImagePickerController : 可以从系统自带的App(照片相机)中获得图片

        // 判断相册是否可以打开

        if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;

        UIImagePickerController *ipc = [[UIImagePickerController alloc] init];

        // 打开照片应用(显示所有相簿)

        ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

        // 打开照片应用(只显示"时刻"这个相簿)

        // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

        // 照相机

        // ipc.sourceType = UIImagePickerControllerSourceTypeCamera;

        ipc.delegate = self;

        [self presentViewController:ipc animated:YES completion:nil];

    }

    #pragma mark - <UIImagePickerControllerDelegate>

    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

    {

        // 销毁控制器

        [picker dismissViewControllerAnimated:YES completion:nil];

        // 设置图片

        self.imageView.image = info[UIImagePickerControllerOriginalImage];

    }

     2:若是想多选照片:1:可用系统框架:#import <Photos/Photos.h>  2:使用步骤:1:先获得所有相簿,在获得相簿胶卷  

    PHAssetCollection

    2:遍历相簿数组,得到每一个相册照片PHAsset,再利用PHAsset请求获得每一张照片

    3:若想做成系统相簿的样式:1:此界面可采用九宫格搭建,或是采用collection搭建,建议用后者,因为后者可以有循环利用的机制,节省

    内存

    2:如下界面搭建:可以监听每张图片的点击,当点击到某张图片的时候,将封装好的蒙板和对勾,盖在上面,或是再移除

     3:

    ## 获得自定义的所有相簿
    ```objc
    // 获得所有的自定义相簿
    PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍历所有的自定义相簿
    for (PHAssetCollection *assetCollection in assetCollections) {
    
    }
    ```
    
    ## 获得相机胶卷相簿
    ```objc
    // 获得相机胶卷
    PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
    ```
    
    ## 获得某个相簿的缩略图
    ```objc
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    // 同步获得图片, 只会返回1张图片
    options.synchronous = YES;
    
    // 获得某个相簿中的所有PHAsset对象
    PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    for (PHAsset *asset in assets) {
        CGSize size = CGSizeZero;
    
        // 从asset中获得图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            NSLog(@"%@", result);
        }];
    }
    ```
    
    ## 获得某个相簿的原图
    ```objc
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    // 同步获得图片, 只会返回1张图片
    options.synchronous = YES;
    
    // 获得某个相簿中的所有PHAsset对象
    PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    for (PHAsset *asset in assets) {
        CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
    
        // 从asset中获得图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            NSLog(@"%@", result);
        }];
    }
    ```
    
    ## 利用UIImagePickerController挑选图片
    ```objc
    // UIImagePickerController : 可以从系统自带的App(照片相机)中获得图片
    
    // 判断相册是否可以打开
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
    
    UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
    // 打开照片应用(显示所有相簿)
    ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    // 打开照片应用(只显示"时刻"这个相簿)
    // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    // 照相机
    // ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
    ipc.delegate = self;
    [self presentViewController:ipc animated:YES completion:nil];
    
    #pragma mark - <UIImagePickerControllerDelegate>
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
    {
        // 销毁控制器
        [picker dismissViewControllerAnimated:YES completion:nil];
    
        // 设置图片
        self.imageView.image = info[UIImagePickerControllerOriginalImage];
    }
    ```
    
    ## NaN错误
    - 错误起因:0被当做除数, 比如 10 / 0
    
    ## 最简单的方法保存图片到相机胶卷
    ```objc
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    
    /**
     *  通过UIImageWriteToSavedPhotosAlbum函数写入图片完毕后就会调用这个方法
     *
     *  @param image       写入的图片
     *  @param error       错误信息
     *  @param contextInfo UIImageWriteToSavedPhotosAlbum函数的最后一个参数
     */
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
    {
        if (error) {
            [SVProgressHUD showErrorWithStatus:@"图片保存失败!"];
        } else {
            [SVProgressHUD showSuccessWithStatus:@"图片保存成功!"];
        }
    }
    ```
    
    ## 保存图片到自定义相册
    ```objc
    - (IBAction)save {
        /*
         PHAuthorizationStatusNotDetermined,     用户还没有做出选择
         PHAuthorizationStatusDenied,            用户拒绝当前应用访问相册(用户当初点击了"不允许")
         PHAuthorizationStatusAuthorized         用户允许当前应用访问相册(用户当初点击了"好")
         PHAuthorizationStatusRestricted,        因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系)
         */
    
        // 判断授权状态
        PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
        if (status == PHAuthorizationStatusRestricted) { // 因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系)
            [SVProgressHUD showErrorWithStatus:@"因为系统原因, 无法访问相册"];
        } else if (status == PHAuthorizationStatusDenied) { // 用户拒绝当前应用访问相册(用户当初点击了"不允许")
            XMGLog(@"提醒用户去[设置-隐私-照片-xxx]打开访问开关");
        } else if (status == PHAuthorizationStatusAuthorized) { // 用户允许当前应用访问相册(用户当初点击了"好")
            [self saveImage];
        } else if (status == PHAuthorizationStatusNotDetermined) { // 用户还没有做出选择
            // 弹框请求用户授权
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status == PHAuthorizationStatusAuthorized) { // 用户点击了好
                    [self saveImage];
                }
            }];
        }
    }
    
    - (void)saveImage
    {
        // PHAsset : 一个资源, 比如一张图片一段视频
        // PHAssetCollection : 一个相簿
    
        // PHAsset的标识, 利用这个标识可以找到对应的PHAsset对象(图片对象)
        __block NSString *assetLocalIdentifier = nil;
    
        // 如果想对"相册"进行修改(增删改), 那么修改代码必须放在[PHPhotoLibrary sharedPhotoLibrary]的performChanges方法的block中
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            // 1.保存图片A到"相机胶卷"中
            // 创建图片的请求
            assetLocalIdentifier = [PHAssetCreationRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier;
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (success == NO) {
                [self showError:@"保存图片失败!"];
                return;
            }
    
            // 2.获得相簿
            PHAssetCollection *createdAssetCollection = [self createdAssetCollection];
            if (createdAssetCollection == nil) {
                [self showError:@"创建相簿失败!"];
                return;
            }
    
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                // 3.添加"相机胶卷"中的图片A到"相簿"D中
    
                // 获得图片
                PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetLocalIdentifier] options:nil].lastObject;
    
                // 添加图片到相簿中的请求
                PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
    
                // 添加图片到相簿
                [request addAssets:@[asset]];
            } completionHandler:^(BOOL success, NSError * _Nullable error) {
                if (success == NO) {
                    [self showError:@"保存图片失败!"];;
                } else {
                    [self showSuccess:@"保存图片成功!"];;
                }
            }];
        }];
    }
    
    /**
     *  获得相簿
     */
    - (PHAssetCollection *)createdAssetCollection
    {
        // 从已存在相簿中查找这个应用对应的相簿
        PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        for (PHAssetCollection *assetCollection in assetCollections) {
            if ([assetCollection.localizedTitle isEqualToString:XMGAssetCollectionTitle]) {
                return assetCollection;
            }
        }
    
        // 没有找到对应的相簿, 得创建新的相簿
    
        // 错误信息
        NSError *error = nil;
    
        // PHAssetCollection的标识, 利用这个标识可以找到对应的PHAssetCollection对象(相簿对象)
        __block NSString *assetCollectionLocalIdentifier = nil;
        [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
            // 创建相簿的请求
            assetCollectionLocalIdentifier = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:XMGAssetCollectionTitle].placeholderForCreatedAssetCollection.localIdentifier;
        } error:&error];
    
        // 如果有错误信息
        if (error) return nil;
    
        // 获得刚才创建的相簿
        return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionLocalIdentifier] options:nil].lastObject;
    }
    
    - (void)showSuccess:(NSString *)text
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [SVProgressHUD showSuccessWithStatus:text];
        });
    }
    
    - (void)showError:(NSString *)text
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [SVProgressHUD showErrorWithStatus:text];
        });
    }
    ```
    
    ## Xcode插件的安装路径
    ```objc
    /Users/用户名/Library/Application Support/Developer/Shared/Xcode/Plug-ins
    ```
  • 相关阅读:
    WPF 如何创建自己的WPF自定义控件库
    浅谈WPF的VisualBrush
    从Oracle数据库中查询前几个月数据时需要注意的一些问题
    WPF当属性值改变时利用PropertyChanged事件来加载动画
    java array to list
    nGrinder 简易使用教程
    页面json 格式化+颜色高亮
    通过maven test 报org.apache.ibatis.binding.BindingException: Invalid bound statement
    jenkins 多选框
    jstack jstat 简易使用教程
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5792292.html
Copyright © 2011-2022 走看看