美文网首页
个人相册开发(9)

个人相册开发(9)

作者: 小石头呢 | 来源:发表于2019-05-17 11:13 被阅读0次

    一.类似个人相册界面的系统相册界面

    1.创建系统相册的界面XLSystemAlbumController类,利用父类XLBaseViewController以及单独出来的tableView简单的搭建界面

    @interface XLSystemAlbumController ()
    
    /**属性化的XLAlbumTableView*/
    @property (nonatomic,strong) XLAlbumTableView *tableView;
    
    @end
    
    @implementation XLSystemAlbumController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //添加标题
        self.title = @"系统相册";
        
        //避免循环引用
        __weak typeof(self) weakSelf = self;
        
        //添加左边的按钮
        [self addItemWithName:@"Cancel" postion:kButtonPostionTypeLeft complish:^(UIButton *item) {
            
            //判断代理对象有没有实现代理方法
            if ([weakSelf.delegate respondsToSelector:@selector(XLImagesPickerControllerDidCancel:)]) {
                
                //实现代理对象的代理方法
                [weakSelf.delegate XLImagesPickerControllerDidCancel:weakSelf];
            }
        }];
        
        //创建含有tableView的视图
        self.tableView = [XLAlbumTableView showAlbumView:CGRectMake(0, self.navigationController.navigationBar.bottom, SCREEN_WIDTH, SCREEN_HEIGHT-self.navigationController.navigationBar.bottom) ViewType:ViewTypeSystem Array:[[XLSystemAlbumManager sharedSystemAlbum] getAllSystemAlbumArray]  superView:self.view];
    }
    
    @end
    

    2.创建系统相册内部界面XLSystemPictureController类,利用父类XLBaseViewController以及单独出来的collectionView简单的搭建界面

    @interface XLSystemPictureController ()
    
    @end
    
    @implementation XLSystemPictureController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //设置标题
        self.title = self.albumModel.name;
        
        //添加返回按钮
        [self addBackItem:nil];
        
        //避免循环引用
        __weak typeof(self) weakSelf = self;
        
        //添加编辑按钮
        [self addItemWithName:@"Done" postion:kButtonPostionTypeRight complish:^(UIButton *item) {
            
            //判断代理对象有没有实现代理方法
            if ([weakSelf.delegate respondsToSelector:@selector(XLImagesPickerController:didFinishedPickingWithInfo:)]) {
                
                //实现代理对象的代理方法
                [weakSelf.delegate XLImagesPickerController:weakSelf didFinishedPickingWithInfo:[XLSystemAlbumManager sharedSystemAlbum].selectedArray];
            }
        }];
        
        //创建显示相册界面
        [XLPictureCollectionView showCollectionView:CGRectMake(0, self.navigationController.navigationBar.bottom, SCREEN_WIDTH, SCREEN_HEIGHT-self.navigationController.navigationBar.bottom) ViewType:ViewTypeSystem Model:self.albumModel toView:self.view];
        
    }
    
    @end
    

    二.仿照UIImagePickerControllerDelegate协议,系统选择图片返回数据

    1.在系统相册界面的头文件定义一套取消的协议,以及代理的对象

    
    #import "XLBaseViewController.h"
    
    //前向声明
    @class XLSystemAlbumController;
    
    @protocol XLImagesCancelPickerDelegate <NSObject>
    
    //取消
    - (void)XLImagesPickerControllerDidCancel:(XLSystemAlbumController *)picker;
    
    @end
    
    @interface XLSystemAlbumController : XLBaseViewController
    
    //代理的对象
    @property (nonatomic,assign) id<XLImagesCancelPickerDelegate> delegate;
    
    @end
    

    2.在系统相册内部界面的头文件定义一套完成的协议,以及代理的对象

    #import "XLBaseViewController.h"
    #import "XLAlbumModel.h"
    
    //前向声明
    @class XLSystemPictureController;
    
    @protocol XLImagesFinishPickerDelegate <NSObject>
    
    //确定按钮
    - (void)XLImagesPickerController:(XLSystemPictureController *)picker didFinishedPickingWithInfo:(NSArray *)info;
    
    @end
    
    @interface XLSystemPictureController : XLBaseViewController
    
    //代理的对象
    @property (nonatomic,assign) id<XLImagesFinishPickerDelegate> delegate;
    
    /**模型来了*/
    @property (nonatomic,strong) XLAlbumModel *albumModel;
    
    @end
    

    三.创建资源模型

    1.创建一个XLPictureModel类,可以被复用,既充当个人相册资源的模型也可以充当系统相册资源的模型

    2.模型的几个属性以及提供的解析方式的接口

    @interface XLPictureModel : NSObject
    
    /**相册的名称-个人相册界面才会访问到*/
    @property (nonatomic,strong) NSString *albumName;
    
    /**模型名称*/
    @property (nonatomic,strong) NSString *name;
    
    /**资源的缩略图*/
    @property (nonatomic, strong)UIImage *iconImage;
    
    /**资源的原图*/
    @property (nonatomic, strong) UIImage *orgImage;
    
    /**资源的时长*/
    @property (nonatomic, copy) NSString *duration;
    
    /**资源的路径*/
    @property (nonatomic, strong) NSURL *videoPath;
    
    /**资源的状态*/
    @property (nonatomic, assign) BOOL  isSelected;
    
    @end
    

    3.因为XLPictureModel类是我们自己定义的类,没有服从NSCoding协议,无法使用NSKeyedArchiver,NSKeyedUnarchiver保存,读取数据,所以我们服从相应的协议,实现相应的代理方法以及解析数据方法的实现

    #import "XLPictureModel.h"
    
    @interface XLPictureModel ()<NSSecureCoding>
    
    @end
    
    @implementation XLPictureModel
    
    //是否遵循安全编码
    +(BOOL)supportsSecureCoding{
        
        return YES;
    }
    
    //数据存储
    -(void)encodeWithCoder:(NSCoder *)aCoder{
        
        [aCoder encodeObject:self.albumName forKey:@"albumName"];
        
        [aCoder encodeObject:self.name forKey:@"name"];
        
        [aCoder encodeObject:self.iconImage forKey:@"iconImage"];
        
        [aCoder encodeObject:self.orgImage forKey:@"orgImage"];
        
        [aCoder encodeObject:self.duration forKey:@"duration"];
        
        [aCoder encodeObject:self.videoPath forKey:@"videoPath"];
        
        [aCoder encodeInteger:self.isSelected forKey:@"isSelected"];
    }
    
    //数据读取
    -(instancetype)initWithCoder:(NSCoder *)aDecoder{
        
        if (self = [super init]) {
            
            self.albumName = [aDecoder decodeObjectForKey:@"albumName"];
            
            self.name = [aDecoder decodeObjectForKey:@"name"];
            
            self.iconImage = [aDecoder decodeObjectForKey:@"iconImage"];
            
            self.orgImage = [aDecoder decodeObjectForKey:@"orgImage"];
            
            self.duration = [aDecoder decodeObjectForKey:@"duration"];
            
            self.videoPath = [aDecoder decodeObjectForKey:@"videoPath"];
            
            self.isSelected = [aDecoder decodeIntegerForKey:@"isSelected"];
        }
        
        return self;
    }
    
    @end
    

    四.创建一个类用于管理系统相册的一些操作

    1.创建一个XLSystemAlbumManager,用于管理一些系统相册的操作

    2.在.h文件定义一些接口,用于获得系统相册的数据

    @interface XLSystemAlbumManager : NSObject
    
    /**一个相册的所有资源数组*/
    @property (nonatomic,strong) NSMutableArray *pictureModelArray;
    
    /**临时资源数组*/
    @property (nonatomic,strong) NSMutableArray *selectedArray;
    
    //单例方式
    +(XLSystemAlbumManager *)sharedSystemAlbum;
    
    //是否授权
    +(BOOL)isXLHaveAuthorityWithType:(ActionType)type;
    
    //获得所有的系统相册
    -(NSMutableArray<XLAlbumModel *> *)getAllSystemAlbumArray;
    
    //获取某个相册的所有图片
    -(NSMutableArray<XLPictureModel *> *)getAllPictureInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending;
    
    @end
    

    3.实现相应的接口

    //静态全局变量
    static XLSystemAlbumManager *instance = nil;
    
    @implementation XLSystemAlbumManager
    
    #pragma mark -------单例模式 ---------
    +(XLSystemAlbumManager *)sharedSystemAlbum{
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            instance = [XLSystemAlbumManager new];
        });
        
        return instance;
    }
    
    #pragma mark -------是否授权 ---------
    +(BOOL)isXLHaveAuthorityWithType:(ActionType)type{
        
        //判断什么类型是否授权
        if (type == ActionTypeLibrary) {
            
            //系统相册
            PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
            if (status == PHAuthorizationStatusAuthorized || status == PHAuthorizationStatusNotDetermined){
                //授予权限了 或者 还没有做出决定
                return YES;
            }else{
                return NO;
            }
        }else{
            
            //相机
            AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
            
            if (status == AVAuthorizationStatusAuthorized || status == AVAuthorizationStatusNotDetermined){
                // 授予权限了 或者 还没有做出决定
                return YES;
            }else{
                return NO;
            }
        }
    }
    
    #pragma mark -------获得所有的系统相册 ---------
    -(NSMutableArray<XLAlbumModel *> *)getAllSystemAlbumArray{
        
        //创建数组存放一个个系统相册
        NSMutableArray<XLAlbumModel *> *listArray = [NSMutableArray array];
        
        //获取所有的系统相册
        PHFetchResult *smartAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        
        //遍历PHFetchResult里面的内容(一个个的相册 PHAssetColletion)
        [smartAlbum enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            //得到obj对应的类型 一个相册 PHAssetCollection
            PHAssetCollection *collection = (PHAssetCollection *)obj;
            
            //最近删除和视频排除
            if (![collection.localizedTitle isEqualToString:@"Recently Deleted"]) {
                
                //取得一个相册下的所有资源
                PHFetchResult *assetResult = [self fetchAssetsInAssetCollection:collection ascending:NO];
            
                //如果相册里面资源的个数大于0
                if (assetResult.count > 0) {
                    
                    //创建模型
                    XLAlbumModel *model = [XLAlbumModel new];
                    
                    //相册的封面图
                    [self getImageByAsset:assetResult.firstObject completion:^(UIImage *img) {
                        
                        model.icon = img;
                    }];
                    
                    //相册名
                    model.name = [XLFactory transformAblumTitle:collection.localizedTitle];
                    
                    //相册的图片数量和视频数量
                    //遍历PHFetchResult里面的内容(一个个的资源 PHAsset)
                    [assetResult enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        
                        //将obj转化为对应的资源类型 PHAsset 图片 视频
                        PHAsset *asset = (PHAsset *)obj;
                        
                        //判断资源的类型
                        if (asset.mediaType == PHAssetMediaTypeImage) {
                            
                            //资源是图片
                            model.photoNumber++;
                        }else if(asset.mediaType == PHAssetMediaTypeVideo){
                            
                            //资源是视频
                            model.videoNumber++;
                            
                        }
                        
                    }];
                    
                    //相册
                    model.assetCollection = collection;
                    
                    //保存到数组中
                    [listArray addObject:model];
                }
            }
            
        }];
        
        return listArray;
    }
    
    #pragma mark -------获取某个相册的所有图片 ---------
    -(NSMutableArray<XLPictureModel *> *)getAllPictureInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending{
        
        //创建数组存放一个个资源
        NSMutableArray<XLPictureModel *> *assetsArray = [NSMutableArray array];
        
        //获得资源的集合体
        PHFetchResult *assetResult = [self fetchAssetsInAssetCollection:assetCollection ascending:ascending];
        
        //遍历PHFetchResult里面的内容(一个个的资源 PHAsset)
        [assetResult enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            //将obj转化为对应的资源类型 PHAsset 图片 视频
            PHAsset *asset = (PHAsset *)obj;
            
            //判断资源的类型
            if (asset.mediaType == PHAssetMediaTypeImage) {
                
                //资源是图片
                [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(100, 100) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                    
                    //创建模型
                    XLPictureModel *model = [XLPictureModel new];
                    
                    //缩略图
                    model.iconImage = result;
                    
                    //原图
                    [XLFactory getImageByAsset:asset completion:^(UIImage *img) {
                        model.orgImage = img;
                    }];
                    
                    //临时路径
                    model.videoPath = [XLFactory copyAssetToTmp:asset];
                    
                    //保存到数组里面
                    [assetsArray addObject:model];
                }];
                
            }else if(asset.mediaType == PHAssetMediaTypeVideo){
                
                //资源是视频
                
                //创建模型
                XLPictureModel *model = [XLPictureModel new];
                
                //缩略图
                [self getImageByAsset:asset completion:^(UIImage *img) {
                    
                    model.iconImage = img;
                }];
                
                //原图
                [XLFactory getImageByAsset:asset completion:^(UIImage *img) {
                    model.orgImage = img;
                }];
        
                //时长
                model.duration = [self getDurationWithAsset:asset];
                
                //路径
                model.videoPath = [XLFactory copyAssetToTmp:asset];
                
                //保存到数组里面
                [assetsArray addObject:model];
            }
        }];
    
        return assetsArray;
    }
    
    #pragma mark -------对某个相册的处理 ---------
    -(PHFetchResult *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending{
        
        //获取的资源按照创建时间排序 ascending 是否升序
        PHFetchOptions *option = [[PHFetchOptions alloc] init];
        option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];
        
        //获取这个相册的所有图片资源
        PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:assetCollection options:option];
        
        return result;
    }
    
    #pragma mark -------获取asset对应的图片 ---------
    -(void)getImageByAsset:(PHAsset *)asset completion:(void (^)(UIImage *img))completion{
        
        //控制图像的质量,裁剪等实例
        PHImageRequestOptions *options = [PHImageRequestOptions new];
        
        //图片质量 高质量
        options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
        
        //图片尺寸 精确提供要求的尺寸
        options.resizeMode = PHImageRequestOptionsResizeModeExact;
        
        //同步
        options.synchronous = YES;
        
        //获取图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(100, 100) contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
           
            completion(result);
        }];
    }
    
    #pragma mark -------获取asset对应的时长 ---------
    -(NSString *)getDurationWithAsset:(PHAsset *)asset{
    
        //解析视频的时长
        NSInteger time = (NSInteger)asset.duration;
        
        //hour
        int hour = time / 60.0 / 60.0;
        //min
        int min = time / 60.0 - hour * 60;
        //sec
        int sec = time % 60;
        
        //定义一个变量接受时长
        NSString *duration;
        
        //判断小时是否为空
        if (hour == 0) {
            duration = [NSString stringWithFormat:@"%02d:%02d", min, sec];
        } else{
            duration = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min, sec];
        }
        
        return duration;
    }
    
    @end
    

    4.在XLFactory中加入我们需要的方法

    #pragma mark -------更改系统相册名称 ---------
    +(NSString *)transformAblumTitle:(NSString *)title{
        
        if ([title isEqualToString:@"Slo-mo"]) {
            return @"慢动作";
        } else if ([title isEqualToString:@"Recently Added"]) {
            return @"最近添加";
        } else if ([title isEqualToString:@"Favorites"]) {
            return @"最爱";
        } else if ([title isEqualToString:@"Recently Deleted"]) {
            return @"最近删除";
        } else if ([title isEqualToString:@"Videos"]) {
            return @"视频";
        } else if ([title isEqualToString:@"All Photos"]) {
            return @"所有照片";
        } else if ([title isEqualToString:@"Selfies"]) {
            return @"自拍";
        } else if ([title isEqualToString:@"Screenshots"]) {
            return @"屏幕快照";
        } else if ([title isEqualToString:@"Camera Roll"]) {
            return @"相机胶卷";
        }else if ([title isEqualToString:@"My Photo Stream"]){
            return @"我的照片流";
        }
        
        return nil;
    }
    
    #pragma mark -------将PHAsset对应的资源保存到tmp目录 ---------
    +(NSURL *)copyAssetToTmp:(PHAsset *)asset{
        
        //PHAssetResource 管理视频的真正数据 data
        PHAssetResource *resource = [[PHAssetResource assetResourcesForAsset:asset] firstObject];
        
        //构建路径
        NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:resource.originalFilename];
        
        //将文件目录转化为NSURL
        NSURL *url = [NSURL fileURLWithPath:tmpPath];
        
        //将这个视频资源保存到临时目录
        [[PHAssetResourceManager defaultManager] writeDataForAssetResource:resource toFile:url options:nil completionHandler:^(NSError * _Nullable error) {
            //保存完需要做什么
        }];
        
        //返回的不是文件目录的URL
        return [NSURL URLWithString:tmpPath];
    }
    
    #pragma mark -------获取asset对应的原图 ---------
    +(void)getImageByAsset:(PHAsset *)asset completion:(void (^)(UIImage *img))completion{
        
        //控制图像的质量,裁剪等实例
        PHImageRequestOptions *options = [PHImageRequestOptions new];
        
        //图片质量 高质量
        options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
        
        //图片尺寸 精确提供要求的尺寸
        options.resizeMode = PHImageRequestOptionsResizeModeExact;
        
        //同步
        options.synchronous = YES;
        
        //获取图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            
            completion(result);
        }];
    }
    

    相关文章

      网友评论

          本文标题:个人相册开发(9)

          本文链接:https://www.haomeiwen.com/subject/wnivaqtx.html