本篇只讨论PhAsset,关于ALAsset,网上很多资料。这里就不再讨论。
曾几何时,项目中访问IPhone的系统相册,选中需要上传的照片或视频,使用webdav上传到自己的私有云中的需求。
从ios8开始,苹果推出了PhAsset,ios9以后ALAsset就不能在使用。我相信大家都用惯了ALAsset,里面的方法特别的好用,尤其是获取相册中没有照片的路径的时候,更是怀恋。
PhAsset获取照片、视频在相册中的路径的时候,就没有那么的方便。
访问相册一般就是以下几个步骤:
无非就是申请访问相册的权限,获取相册分组
获取相册中的相册组
点击进入到具体的相册中组中,选中需要上传的图片进行上传
马上想到去找度娘、简书。但是,不知道是我搜索的姿势不对,还是什么原因,并没有找到获取该对象在相册中的路径、要不然就是不能用的方法。
好了废话少说,进入正题,具体分以下几个步骤:
1)申请访问相册的权限(每次进入去访问系统相册的时候,都是需要去查看权限)
2)获取相册中的所有的照片、视频
3)获取具体某一个对象的路径
一:申请权限
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
//没有授权
if(status== PHAuthorizationStatusRestricted) {
complate(nil);
}
else if (status==PHAuthorizationStatusDenied) {
complate(nil);
}
else {//已经授权
}
}];
1)如果没有授权,需要提示用户去授权,否则访问不了相册
NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
NSString *appName = [info objectForKey:@"CFBundleDisplayName"];
appName = appName ? appName : [info objectForKey:@"CFBundleName"];
NSString *message = [NSString stringWithFormat:@"请在系统设置中允许“%@”访问照片!", appName];
[[[UIAlertView alloc]initWithTitle:@"无法访问照片" message:message delegate:self cancelButtonTitle:@"我知道了!" otherButtonTitles:nil] show];
二)允许访问后,获取相册中的资源
NSMutableArray<PHAsset *> *assets = [NSMutableArray array];
PHFetchOptions *option = [[PHFetchOptions alloc] init];
//ascending 为YES时,按照照片的创建时间升序排列;为NO时,则降序排列
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];
PHAssetMediaType type = self.type==5 ? PHAssetMediaTypeImage:PHAssetMediaTypeVideo;
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:type options:option];
__weak typeof(self) weakSelf= self;
__strong typeof(weakSelf) strongSelf=weakSelf;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[result enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHAsset *asset = (PHAsset *)obj;
NSInteger type = asset.mediaType;
//照片
if(strongSelf.type==5&&type==1){
[assets addObject:asset];
}
else if (strongSelf.type==2&&type==2){
[assets addObject:asset];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
complate(assets);
});
});
获取到相册中的资源,接下来就是获取到具体某一个对象,显示到界面上
三)获取具体某一个asset的对象,如果是视频,那么直接获取首帧的图像
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
/**
resizeMode:对请求的图像怎样缩放。有三种选择:None,默认加载方式;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。
deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。
这个属性只有在 synchronous 为 true 时有效。
*/
option.resizeMode = resizeMode;//控制照片尺寸
//option.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;//控制照片质量
//option.synchronous = YES;
option.networkAccessAllowed = YES;
//param:targetSize 即你想要的图片尺寸,若想要原尺寸则可输入PHImageManagerMaximumSize
[[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {
completion(image);
}];
获取到需要上传的文件后,那就是需要上传文件
那么上传文件就有两种方法:
1)把需要上传的文件读成data去上传
2)获取在相册中的路径,根据路径去上传
读成data,是比较方便。我们知道,data是需要占我们的运行内存。如果文件比较大的时候,有可能app就因为收到内存警告,占用内存再大,就会导致app奔溃。还要就是,data比较大的时候,上传也是一个比较繁琐的事情。
利用路径去上传文件的话,就不会出现上面说的那种情况,只需要跑一个线程去进行这个任务,我并不用太关心内存的开销。但是,比较麻烦的是,怎么去获取在相册中的路径。网上一直没有找到具体的方法。
解决思路:
1)首先想到了alasset的获取照片思路:
ALAssetRepresentation * representation = [(ALAsset *)asset defaultRepresentation];
model.URLInPotoes = [representation url];
model.imageName=[representation filename];
[photos addObject:model];
在phasset中,并没有找到这样的方法。
2)反向获取url
1.获取照片的url
[[PHImageManager defaultManager] requestImageForAsset:phAsset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSURL * url = [info objectForKey:@"PHImageFileURLKey"];
complate(url);
}];
2.获取视频的地址
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
NSString * url = [[[info objectForKey:@"PHImageFileSandboxExtensionTokenKey"]componentsSeparatedByString:@";"] lastObject];
complate(url);
}];
注意:相册中Icloud类型的照片、视频只是相当于是一个链接,所以并不能获取该类型文件的链接
如果,有好的方法,请联系我。