个人相册开发(11)
一.回调系统相册被选择的资源
1.因为我们通过单例模式创建XLSystemAlbumManager,所以它会在整个程序的运行过程中一直存活,没有被释放掉。这样我们就可以通过添加一个数组变量来记录被选中的系统相册资源
//.h
/**临时资源数组*/
@property (nonatomic,strong) NSMutableArray *selectedArray;
//.m
//临时选中的资源数组
-(NSMutableArray *)selectedArray{
if (_selectedArray == nil) {
//初始化
_selectedArray = [NSMutableArray array];
}
return _selectedArray;
}
2.改变相应的模型的isSelected,以及通过changeStatus方法改变相应Cell的勾选状态,并对勾选的模型,加入到我们的临时数组中
//item被点击了
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//判断类型
if (self.type == ViewTypePerson) {
//个人相册
//判断是不是第一个被点击了
if (indexPath.row == 0) {
}else{
//第一个之外的被点击了
//判断是不是编辑状态
if (self.isEditing) {
}else{
//进入浏览界面
}
}
}else{
//系统相册
//获取indexPath.row对应的model
XLPictureModel *model = self.pictureModelArray[indexPath.row];
//更改isSelected的状态
model.isSelected = !model.isSelected;
//获取当前的cell
XLPictureCell *cell = (XLPictureCell*)[collectionView cellForItemAtIndexPath:indexPath];
//将状态传递给cell
[cell changeStatus:model.isSelected];
//判断资源有没有被选中
if (model.isSelected == YES) {
//加入临时资源数组中
[[XLSystemAlbumManager sharedSystemAlbum].selectedArray addObject:model];
}else{
//从临时资源数组中移除
[[XLSystemAlbumManager sharedSystemAlbum].selectedArray removeObject:model];
}
}
}
3.当系统相册内部界面的Done按钮被点击,触发其代理方法
1.同样因为我们通过单例模式创建XLSystemAlbumManager,它会在整个程序的运行过程中一直存活,没有被释放掉。这样我们就可以通过添加一个数组变量来记录保存添加到个人相册的系统相册资源
提前在StringConstants里面加入IN_FILE_PATH
//存储相册内部信息的文件路径
#define IN_FILE_PATH [[[XLFileManager sharedManager] docPath] stringByAppendingPathComponent:@"pictureData"]
//.h
/**被添加的所有资源数组*/
@property (nonatomic,strong) NSMutableArray *pictureModelArray;
//.m
//资源数组
-(NSMutableArray *)pictureModelArray{
if (_pictureModelArray == nil) {
//初始化
_pictureModelArray = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithFile:IN_FILE_PATH]];
}
return _pictureModelArray;
}
2.同时在XLSystemAlbumManager添加一个接口modelsArrayChanged用于刷新个人相册内部界面和更新IN_FILE_PATH里面的内容
提前在StringConstants里面加入刷新个人相册内部界面的消息
#define kPictureModelsArrarChangeNotificationName @"kPictureModelsArrarChangeNotificationName"
#pragma mark -------刷新个人相册内部界面和更新IN_FILE_PATH里面的内容 ---------
-(void)modelsArrayChanged{
//发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:kPictureModelsArrarChangeNotificationName object:nil];
//NSKeyedArchiver保存数据
[NSKeyedArchiver archiveRootObject:self.pictureModelArray toFile:IN_FILE_PATH];
}
3..Done被点击后,因为选中的模型里面的isSelected需要被再次使用,而他们只有为YES的状态才会被添加到info里面,所以为了避免后续的错误,我们首先就需要将所有的模型的isSelected的状态复原,然后回调数据保存,将模型加入到相应的XLSystemAlbumManager的存放被选中的资源数组。最后一定要清空临时保存从系统相册选中的资源的数组,防止下一次使用出错。
//Done按钮被点击了
-(void)XLImagesPickerController:(XLSystemPictureController *)picker didFinishedPickingWithInfo:(NSArray *)info{
//移除视图
[picker dismissViewControllerAnimated:YES completion:nil];
//恢复选中的状态
for (XLPictureModel *model in info) {
model.isSelected = NO;
}
//回调资源的模型数据
if (self.PickerBlock) {
self.PickerBlock(info);
}
//保存到资源数组中
[[XLSystemAlbumManager sharedSystemAlbum].pictureModelArray addObjectsFromArray:info];
//清空临时资源数组上一次选中的所有内容
[[XLSystemAlbumManager sharedSystemAlbum].selectedArray removeAllObjects];
//刷新数据
[[XLSystemAlbumManager sharedSystemAlbum] modelsArrayChanged];
}
4.接着上移步骤的数据回调保存,在个人相册界面的第一个cell被点击的相册来源表中选择相册的情况,XLImagePicker的创建方法的block里面具体执行。在这里我们补充完整模型的数据,名字以及更改将videoPath由tmp下面的目录改为video对应的目录
[XLImagePicker showPickerWithType:ActionTypeLibrary handle:^(NSArray<XLPictureModel *> *pictureModelArray) {
//保存数据
for (XLPictureModel *model in pictureModelArray){
//保存相册名称
model.albumName = self.albumModel.name;
//判断是视频还是图片
if (model.duration.length > 0) {
//视频
//保存视频
NSURL *url = [[XLAlbumManager sharedManager] addVideo:model.videoPath Image:model.orgImage thumbImage:model.iconImage toAlbum:self.albumModel.name];
//更换path
model.videoPath = url;
//加入名字,利用url
model.name = url.absoluteString;
} else{
//图片
//保存图片
NSString *name = [[XLAlbumManager sharedManager] addImage:model.orgImage thumbImage:model.iconImage toAlbum:self.albumModel.name];
model.name = name;
}
}
}];
5.上一步骤需要在XLAlbumManager中添加两个接口用来保存图片和视频
//添加内容 图片
-(NSString *)addImage:(UIImage *)image thumbImage:(UIImage *)thumbImage toAlbum:(NSString *)name;
//添加内容 视频
-(NSURL *)addVideo:(NSURL *)videoPath Image:(UIImage *)image thumbImage:(UIImage *)thumbImage toAlbum:(NSString *)name;
具体的实现,在实现的同时刷新个人相册界面数据
#pragma mark -------相册中添加内容 图片 ---------
-(NSString *)addImage:(UIImage *)image thumbImage:(UIImage *)thumbImage toAlbum:(NSString *)name{
NSString *picname;
//改变相册对应的模型数据;
for (XLAlbumModel *model in self.albumModelsArray) {
//判断是不是这个相册
if ([model.name isEqualToString:name]) {
//处理封面图片
if (model.photoNumber == 0 && model.videoNumber == 0) {
model.icon = thumbImage;
}
//图片个数
model.photoNumber++;
//保存这个图片到Documents路径
picname = [[XLFileManager sharedManager] saveImage:image thumImage:thumbImage toAlbum:name];
//刷新个人相册界面
[self modelsArrayChanged];
//跳出循环
break;
}
}
return picname;
}
#pragma mark -------相册中添加内容 视频 ---------
-(NSURL *)addVideo:(NSURL *)videoPath Image:(UIImage *)image thumbImage:(UIImage *)thumbImage toAlbum:(NSString *)name{
NSURL *url;
//改变相册对应的模型数据;
for (XLAlbumModel *model in self.albumModelsArray) {
//判断是不是这个相册
if ([model.name isEqualToString:name]) {
//处理封面图片
if (model.photoNumber == 0 && model.videoNumber == 0) {
model.icon = thumbImage;
}
//视频个数
model.videoNumber++;
//保存这个视频到Documents路径
url = [[XLFileManager sharedManager] saveVideo:videoPath image:image thumImage:thumbImage toAlbum:name];
//刷新个人相册界面
[self modelsArrayChanged];
//跳出循环
break;
}
}
return url;
}
6.上一步骤需要在XLFileManager添加两个接口用来保存图片和视频
//保存图片
-(NSString *)saveImage:(UIImage *)image thumImage:(UIImage *)thumImage toAlbum:(NSString *)albumName;
//保存视频
-(NSURL *)saveVideo:(NSURL *)videoPath image:(UIImage *)image thumImage:(UIImage *)thumImage toAlbum:(NSString *)albumName;
具体的实现,实现的同时,返回数据设置模型的name和videoPath
#pragma mark -------保存图片文件 ---------
-(void)saveDataWithName:(NSString *)name MediaType:(MediaType)mediaType Picture:(PictureType)picType Image:(UIImage *)img toAlbum:(NSString *)albumName{
//获取路径
NSString *path = [[self pathWithName:albumName mediaType:mediaType pictureType:picType] stringByAppendingPathComponent:name];
//创建文件
NSData *data = UIImagePNGRepresentation(img);
//写入文件
[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
}
#pragma mark -------保存图片 ---------
-(NSString *)saveImage:(UIImage *)image thumImage:(UIImage *)thumImage toAlbum:(NSString *)albumName{
//获取文件的名字
NSString *name = [NSString stringWithFormat:@"%f",[NSDate date].timeIntervalSince1970];
//保存缩略图
[self saveDataWithName:name MediaType:MediaTypePicture Picture:PictureTypeSmall Image:thumImage toAlbum:albumName];
//保存原图
[self saveDataWithName:name MediaType:MediaTypePicture Picture:PictureTypeOrg Image:image toAlbum:albumName];
return name;
}
#pragma mark -------保存图片 ---------
-(NSURL *)saveVideo:(NSURL *)videoPath image:(UIImage *)image thumImage:(UIImage *)thumImage toAlbum:(NSString *)albumName{
//获取文件的名字
NSString *name = [NSString stringWithFormat:@"%f",[NSDate date].timeIntervalSince1970];
//保存缩略图
[self saveDataWithName:name MediaType:MediaTypeVideo Picture:PictureTypeSmall Image:thumImage toAlbum:albumName];
//保存原图
[self saveDataWithName:name MediaType:MediaTypeVideo Picture:PictureTypeOrg Image:image toAlbum:albumName];
//获得video对应存放视频的目录
NSString *vPath = [[self pathWithName:albumName mediaType:MediaTypeVideo pictureType:PictureTypeVideo] stringByAppendingPathComponent:[name stringByAppendingString:@".mov"]];
//将tmp目录的视频copy到video对应的目录里面
[[NSFileManager defaultManager] copyItemAtPath:videoPath.absoluteString toPath:vPath error:nil];
//更换videoPath
return [NSURL fileURLWithPath:vPath];
}
二.回调相机的资源
1.因为相机获取的视频没有相关的PHAsset资源,所以我我们在XLFactory中加入一个方法获取其第一帧图片以及时长
#pragma mark -------获取视频路径对应的第一帧的图片以及时长 ---------
+(void)firstImageWithVideoURL:(NSURL *)url handel:(void(^)(UIImage *img,NSString *time))block{
//获取视频第一帧
NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:opts];
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
generator.appliesPreferredTrackTransform = YES;
generator.maximumSize = CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT);
CGImageRef img = [generator copyCGImageAtTime:CMTimeMake(0, 10) actualTime:NULL error:nil];
//获取图片
UIImage *image = [UIImage imageWithCGImage:img];
//获取时间
long long time = urlAsset.duration.value/urlAsset.duration.timescale;
int hour = time/60.0/60.0;
int minute = time/60.0-hour*60;
int second = time%60;
NSString *duration;
if (hour == 0) {
duration = [NSString stringWithFormat:@"%02d:%02d",minute,second];
}else{
duration = [NSString stringWithFormat:@"%02d:%02d:%02d",hour,minute,second];
}
//回调数据
block(image,duration);
}
2.相机的代理方法
//点击Cancel按钮
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
//移除imagePickerController
[picker dismissViewControllerAnimated:YES completion:nil];
}
//内容被封装在info里面
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
//移除imagePickerController
[picker dismissViewControllerAnimated:YES completion:nil];
//获得类型
NSString *type = [info objectForKey:@"UIImagePickerControllerMediaType"];
//创建模型
XLPictureModel *model = [XLPictureModel new];
//判断
if ([type isEqualToString:@"public.image"]) {
//相册
//原图
model.orgImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
//缩略图
model.iconImage = [model.orgImage scaleToSize:CGSizeMake(kSize, kSize)];
//回调数据
if (self.PickerBlock) {
self.PickerBlock(@[model]);
}
}else{
//视频
NSURL *url = [info objectForKey:@"UIImagePickerControllerMediaURL"];
[XLFactory firstImageWithVideoURL:url handel:^(UIImage *img, NSString *time) {
//原图
model.orgImage = img;
//缩略图
model.iconImage = [model.orgImage scaleToSize:CGSizeMake(kSize, kSize)];
//时长
model.duration = time;
//路径
model.videoPath = url;
//回调数据
if (self.PickerBlock) {
self.PickerBlock(@[model]);
}
}];
}
}
3.同样的对回调数据的保存
[XLImagePicker showPickerWithType:ActionTypeCamera handle:^(NSArray<XLPictureModel *> *pictureModelArray) {
//保存数据
for (XLPictureModel *model in pictureModelArray){
//保存相册名称
model.albumName = self.albumModel.name;
//判断是视频还是图片
if (model.duration.length > 0) {
//视频
//保存视频
NSURL *url = [[XLAlbumManager sharedManager] addVideo:model.videoPath Image:model.orgImage thumbImage:model.iconImage toAlbum:self.albumModel.name];
//更换path
model.videoPath = url;
} else{
//图片
//保存图片
[[XLAlbumManager sharedManager] addImage:model.orgImage thumbImage:model.iconImage toAlbum:self.albumModel.name];
}
}
}];