一.类似个人相册界面的系统相册界面
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);
}];
}
网友评论