[iOS]自定义图片选择器

Demo:https://github.com/Gamin-fzym/GACustomPhotoSelector
本文的产生,因今年夏季被面试时有被问到的一个问题。有没有自定义过相片选择器?于是抽空查资料写一个简单demo放在这里。
内容:
1.写了一个“自定义图片选择器”。
2.获取到图片后为了剪切图片使用了工具“PureCamera”。
3.将编辑后的图片保存到自定义相册。
4.最后为自定义图片选择器添加了多选功能。

demo示意图:


首页(HomeViewController)
首页示意图:
[iOS]自定义图片选择器_第1张图片

#import "HomeViewController.h"
#import 
#import "TOCropViewController.h"
#import "PureCamera.h"
#import "ListViewController.h"
#import "SVProgressHUD.h"
#import "GACustomSelectPIC.h"
#import "GACustomSelectProtocol.h"
#import "GAPublicMethod.h"

@interface HomeViewController () 
@property (weak, nonatomic) IBOutlet UIButton *photoBut;
@property (strong, nonatomic) UIImage *displayImg;
@property (strong, nonatomic) UIImagePickerController *ipc;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

@end

@implementation HomeViewController

- (void)entryListVCWith:(UIImage *)image {
    _displayImg = image;
    [_photoBut setBackgroundImage:image forState:UIControlStateNormal];

    ListViewController *lVC = [[ListViewController alloc] initWithNibName:@"ListViewController" bundle:nil];
    lVC.img = image;
    [self.navigationController pushViewController:lVC animated:YES];
}

- (IBAction)tapPhotoAction:(id)sender {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self selectTakePhoto];
    }];
    [alert addAction:cameraAction];
    
    UIAlertAction *albumAction = [UIAlertAction actionWithTitle:@"从相册中选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self selectAlbum];
    }];
    [alert addAction:albumAction];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {}];
    [alert addAction:cancelAction];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)selectTakePhoto {
    // 引用相机
    PureCamera *homec = [[PureCamera alloc] init];
    __weak typeof(self)myself = self;
    homec.fininshcapture = ^(UIImage *image){
        if (image) {
            [myself entryListVCWith:image];
        }
    } ;
    [self presentViewController:homec animated:NO completion:^{}];
}

- (void)selectAlbum {
    if (!self.ipc) {
        self.ipc = [[UIImagePickerController alloc] init];
        self.ipc.delegate = self;
        self.ipc.navigationBar.translucent = NO;
        self.ipc.edgesForExtendedLayout = UIRectEdgeNone;
        //self.ipc.allowsEditing = YES;
    }
    self.ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentViewController:self.ipc animated:YES completion:^{}];
}

#pragma mark - UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 从info取出此时摄像头的媒体类型
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
        // 获取照片的原图
        UIImage *original = [info objectForKey:UIImagePickerControllerOriginalImage];

        // 引用图片裁剪页
        TOCropViewController *cropController = [[TOCropViewController alloc] initWithImage:original aspectRatioStle:TOCropViewControllerAspectRatioOriginal];
        cropController.delegate = self;
        // [self pushViewController:cropController animated:YES];
        [picker presentViewController:cropController animated:YES completion:nil];
    } else {
        [picker dismissViewControllerAnimated:YES completion:^{}];
    }
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:^{}];
}

#pragma mark - TOCropViewControllerDelegate

- (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle {
    if (image) {
        //[cropViewController.navigationController popViewControllerAnimated:YES];
        [cropViewController dismissViewControllerAnimated:YES completion:nil];
        [_ipc dismissViewControllerAnimated:NO completion:^{}];
        [self entryListVCWith:image];
    }
}

- (void)cropViewController:(nonnull TOCropViewController *)cropViewController didFinishCancelled:(BOOL)cancelled {
    [cropViewController dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - 自定义图片选择器

- (IBAction)customSelectPicture:(id)sender {
    GACustomSelectPIC *custom = [[GACustomSelectPIC alloc] initWithNibName:@"GACustomSelectPIC" bundle:nil];
    custom.delegate = self;
    custom.tempLimitMax = 5;
    [self.navigationController pushViewController:custom animated:YES];
}

#pragma mark - GACustomSelectProtocol

- (void)customSelectAssets:(NSMutableArray *)assets {
    NSArray *subViews = [self.scrollView subviews];
    for (int i = 0 ; i < subViews.count ; i ++) {
        UIView *tempView = [subViews objectAtIndex:i];
        [tempView removeFromSuperview];
    }
    
    float width = self.scrollView.bounds.size.height;
    NSMutableArray *selectImages = [NSMutableArray new];
    for (int i = 0 ; i < assets.count ; i ++) {
        id tempAsset = [assets objectAtIndex:i];
        [self fetchImageWithAsset:tempAsset imageBlock:^(UIImage * _Nonnull image) {
            [selectImages addObject:image];
            //NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
            UIImageView *tempIV = [UIImageView new];
            tempIV.frame = CGRectMake(i*width, 0, width, width);
            tempIV.image = image;
            tempIV.contentMode = UIViewContentModeScaleAspectFill;
            [tempIV.layer setMasksToBounds:YES];
            [self.scrollView addSubview:tempIV];
            [self.scrollView setContentSize:CGSizeMake(CGRectGetMaxX(tempIV.frame), width)];
        }];
    }
}
    
@end

列表页(ListViewController)
展示剪切后的图片,保存图片到自定义的相册
展示剪切图片示意图:
[iOS]自定义图片选择器_第2张图片

保存图片到自定义相册:

[iOS]自定义图片选择器_第3张图片

#import "ListViewController.h"
#import 
#import "SVProgressHUD.h"

@interface ListViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *playIV;

@end

@implementation ListViewController

- (IBAction)savePictureAction:(id)sender {
    /**
    获取用户授权状态
    typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
        PHAuthorizationStatusNotDetermined = 0, // 不确定
        PHAuthorizationStatusRestricted,        // 家长控制,拒绝
        PHAuthorizationStatusDenied,            // 拒绝
        PHAuthorizationStatusAuthorized         // 授权
    } PHOTOS_AVAILABLE_IOS_TVOS_OSX(8_0, 10_0, 10_13);
    */
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusNotDetermined) {
        // 如果状态是不确定的话,block中的内容会等到授权完成再调用
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) {
                [self savePhoto];
            }
        }];
    } else if (status == PHAuthorizationStatusAuthorized) {
        [self savePhoto];
    } else {
        // 提示用户去打开授权
        [SVProgressHUD showInfoWithStatus:@"进入设置界面->找到当前应用->打开允许访问相册开关"];
    }
}

#pragma mark - 该方法获取在图库中是否已经创建该App的相册
// 该方法的作用,获取系统中所有的相册进行遍历,若是已有该相册则返回该相册,若是没有该相册则返回nil,参数为需要创建的相册名称
- (PHAssetCollection *)fetchAssetColletion:(NSString *)albumTitle {
    // 获取所有的相册
    PHFetchResult *result = [PHAssetCollection           fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍历相册数组
    for (PHAssetCollection *assetCollection in result) {
        if ([assetCollection.localizedTitle isEqualToString:albumTitle]) {
            return assetCollection;
        }
    }
    return nil;
}

#pragma mark - 保存图片的方法

- (void)savePhoto {
    // 修改系统相册用PHPhotoLibrary单例
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        // 调用判断是否已有该名称相册
        PHAssetCollection *assetCollection = [self fetchAssetColletion:@"测试相册"];
        // 创建一个操作图库的对象
        PHAssetCollectionChangeRequest *assetCollectionChangeRequest;
        if (assetCollection) {
            // 已有相册则获取该相册
            assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
        } else {
            // 没有该相册则创建自定义相册
            assetCollectionChangeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:@"测试相册"];
        }
        // 保存你需要保存的图片到自定义相册
        PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:self.playIV.image];
        // 这个block是异步执行的,使用占位图片先为图片分配一个内存,等到有图片的时候,再对内存进行赋值
        PHObjectPlaceholder *placeholder = [assetChangeRequest placeholderForCreatedAsset];
        [assetCollectionChangeRequest addAssets:@[placeholder]];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (error) {
             [SVProgressHUD showErrorWithStatus:@"保存失败"];
        } else {
             [SVProgressHUD showSuccessWithStatus:@"保存成功"];
        }
    }];
}

@end

自定义图片选择器(GACustomSelectPIC)
代码太多,放上效果图,详见demo...
[iOS]自定义图片选择器_第4张图片
自定义图片选择器相册列表:
[iOS]自定义图片选择器_第5张图片
自定义图片选择器图组列表:
[iOS]自定义图片选择器_第6张图片

TO:
PureCamera
iOS 自定义图片选择器 1 - PhotoKit
iOS中怎么存储照片到自定义相册

你可能感兴趣的:([iOS]学习笔记)