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
    ```
  • 相关阅读:
    flock对文件锁定读写操作的问题 简单
    hdu 2899 Strange Fuction(二分)
    hdu 2199 Can you solve this equation? (二分)
    poj 3080 Blue Jeans (KMP)
    poj 2823 Sliding Window (单调队列)
    poj 2001 Shortest Prefixes (trie)
    poj 2503 Babelfish (trie)
    poj 1936 All in All
    hdu 3507 Print Article (DP, Monotone Queue)
    fzu 1894 志愿者选拔 (单调队列)
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5792292.html
Copyright © 2011-2022 走看看