PhotoKit

作者: 携一两本单色书来 | 来源:发表于2018-09-04 17:57 被阅读9次

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 用于处理图像的缓存这里就不说了~~
最后,挂个图:


PhotoKit构成

相关文章

网友评论

      本文标题:PhotoKit

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