title: PhotoKit
date: 2016-11-18 11:05:28
重构遇到的问题:
由于项目重构,将图片选择器重CTAssetsPickerController换成了TZImagePickerController,两者都是优秀的图片选择器
换完之后发现视频上传功能出问题了,原来以前的上传方法是用ALAssetsLibrary上传的,但是看TZImagePickerController发现8以后就使用的Photos Framework。
// If user picking a video, this handle will be called.
// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
// 如果用户选择了一个视频,下面的handle会被执行
// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,id asset);
这是以前上传的两种方法,
ALAsset *asset = [mediaDatas objectAtIndexSafe:0];
NBLog(@"asset=%@, representation=%@, url=%@", asset, [asset defaultRepresentation], [asset defaultRepresentation].url);
if (asset != nil) {
if (/* DISABLES CODE */ (1)) {
NSString *videoPath = [NSDocumentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.mov", 0]]; // 这里直接强制写一个即可,之前计划是用i++来区分不明视频
//可以看出来使用fileURLWithPath创建出来的URL会自动加上协议头
NSURL *url = [NSURL fileURLWithPath:videoPath];
NSError *theErro = nil;
BOOL exportResult = [asset exportDataToURL:url error:&theErro];
NBLog(@"exportResult=%@", exportResult?@"YES":@"NO");
NSData *videoData = [NSData dataWithContentsOfURL:url];
// NSData *videoData = [NSData dataWithContentsOfFile:videoPath];
// [formData appendPartWithFormData:videoData name:@"video1"];
//第一个参数是服务器存你上传视频的文件夹名,第二个参数是你上传视频的名字,随便写。第三个是格式。
[formData appendPartWithFileData:videoData name:@"video1" fileName:@"video1.mov" mimeType:@"video/quicktime"];
}else {
//第一种获取NSData的方式, 上传后, 后台仅获取到文本
//ALAssetRepresentation获取本地相册
ALAssetRepresentation *rep = [asset defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData *videoData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
//传到服务器
//[formData appendPartWithFormData:videoData name:@"video1"];
[formData appendPartWithFileData:videoData name:@"video1" fileName:@"video1" mimeType:@"video/quicktime"];
}
NBLog(@"method 2");
}
新方法:
PHAsset *asset = [mediaDatas objectAtIndexSafe:0];
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
[formData appendPartWithFileData:imageData name:@"video1" fileName:@"video1" mimeType:@"video/quicktime"];
}];
由于现在项目最低8.0,所以就不做ALAssetsLibrary的方法的了。
好了,下面该说一说PHAsset了。
PHAsset:
PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源
PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值
//做选择的约束条件。比如,只获取图片,不获取视频。
phopt.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d",PHAssetMediaTypeImage];//只取图片
//按可指定字段用来对获取结果进行排序
phopt.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]]; // 按图片生成时间排序
phopt.includeHiddenAssets = YES;//获取结果是否包括被隐藏的资源
phopt.includeAllBurstAssets = YES;//获取结果是否包括连拍资源
phopt.wantsIncrementalChangeDetails = YES;//允许变化细节?
PHFetchResult: 表示一系列的资源集合,也可以是相册的集合,可以用类似 NSArray 的接口来访问PHFetchResult结果内的集合。
PHFetchResult *albums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumAllHidden options:nil];
PHAssetCollection: 表示一个相册或者一个时刻,或者是一个「智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等),下面是一些只读属性
assetCollectionType 资源集合类型,比如相册或者“时刻”相册,
enum PHAssetCollectionType : Int {
case Album //从 iTunes 同步来的相册,以及用户在 Photos 中自己建立的相册
case SmartAlbum //经由相机得来的相册
case Moment //Photos 为我们自动生成的时间分组的相册
}
assetCollectionSubtype 子类型
enum PHAssetCollectionSubtype : Int {
case AlbumRegular //用户在 Photos 中创建的相册
case AlbumSyncedEvent //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步过来的事件。然而,在iTunes 12 以及iOS 9.0 beta4上,选用该类型没法获取同步的事件相册,而必须使用AlbumSyncedAlbum。
case AlbumSyncedFaces //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步的人物相册。
case AlbumSyncedAlbum //做了 AlbumSyncedEvent 应该做的事
case AlbumImported //从相机或是外部存储导入的相册,完全没有这方面的使用经验,没法验证。
case AlbumMyPhotoStream //用户的 iCloud 照片流
case AlbumCloudShared //用户使用 iCloud 共享的相册
case SmartAlbumGeneric //文档解释为非特殊类型的相册,主要包括从 iPhoto 同步过来的相册。
case SmartAlbumPanoramas //相机拍摄的全景照片
case SmartAlbumVideos //相机拍摄的视频
case SmartAlbumFavorites //收藏文件夹
case SmartAlbumTimelapses //延时视频文件夹,同时也会出现在视频文件夹中
case SmartAlbumAllHidden //包含隐藏照片或视频的文件夹
case SmartAlbumRecentlyAdded //相机近期拍摄的照片或视频
case SmartAlbumBursts //连拍模式拍摄的照片
case SmartAlbumUserLibrary //这个命名最神奇了,就是相机相册,所有相机拍摄的照片或视频都会出现在该相册中,而且使用其他应用保存的照片也会出现在这里。
case Any //包含所有类型
}
estimatedAssetCount :估算的asset数量,不精确
PHImageManager: 用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格,在框架中是个单例对象,用[PHImageManager defaultManager]获取,它提供了加载图片和视频的方法,
PHImageRequestOptions: 如上面所说,控制加载图片时的一系列参数
PHImageRequestOptions *options= [PHImageRequestOptions new];
//这个属性是指获取的图像是否需要包含系统相册“编辑”功能处理过的信息(如滤镜,旋转等)
options.version = PHImageRequestOptionsVersionCurrent;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
/*
PHImageRequestOptionsDeliveryModeOpportunistic = 0,图片获取速度和质量的平衡
PHImageRequestOptionsDeliveryModeHighQualityFormat = 1,高质量图片,
PHImageRequestOptionsDeliveryModeFastFormat = 2 快速得到图片的情况下保证质量
*/
options.resizeMode = PHImageRequestOptionsResizeModeExact;
/*
PHImageRequestOptionsResizeModeNone = 0,不压缩
PHImageRequestOptionsResizeModeFast,高效率请求,但是返回的图片尺寸可能和要求的尺寸不同
PHImageRequestOptionsResizeModeExact,按照精准尺寸返回
*/
// 同步获得图片, 只会返回1张图片,PS: 若options.synchronous = YES,则不论options.deliveryMode如何设置,系统会选择PHImageRequestOptionsDeliveryModeHighQualityFormat(高质量图片)
options.synchronous = YES;
//是否联网获取iCloud的图片
options.networkAccessAllowed = NO;
//指定作物矩形单元坐标的原始图像,如的脸。默认为CGRectZero(不适用)
options.normalizedCropRect = CGRectMake(100, 200, 100, 100);
options.progressHandler
//一个 PHAssetImageProgressHandler 的 block,当从 iCloud 下载照片时,它就会被图像管理器自动调用还有一个与 iCloud 密切相关的属性当图像需要从 iCloud 下载时,这个 block 会被自动调用,block 中会返回图像下载的进度,图像的信息,出错信息。开发者可以利用这些信息反馈给用户当前图像的下载进度以及状况,但需要注意?progressHandler 不在主线程上执行,因此在其中需要操作 UI,则需要手工放到主线程执行。
options.progressHandler
当然,还有PHImageCachingManager 用于处理图像的缓存这里就不说了~~
最后,挂个图:
![](https://img.haomeiwen.com/i2246303/e977eab7aef819c7.png)
网友评论