美文网首页
个人相册开发(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