美文网首页
Photo Kit 使用总结

Photo Kit 使用总结

作者: AntKing | 来源:发表于2017-06-19 10:56 被阅读0次

    ios访问系统相册的新框架Photo Kit在使用时候感觉还是蛮恶心的,所有总结了一下,整理下来,以备以后使用

    请求相册授权

    • 在info.plist文件中加入下面两个key,一个是访问相册所需,另一个是调用摄像头所需
    
        <key>NSPhotoLibraryUsageDescription</key>
        <string>访问相册</string>
        <key>NSCameraUsageDescription</key>
        <string>使用相机</string>
    
    
    • 获取授权的状态
      鉴于ios对于用户隐私的保护,使用相册时需要用户授权,用户么有授权的时候不能访问相册,
    PHPhotoLibrary 代表整个照片应用,权限的四种状态如下,
    只有PHAuthorizationStatusAuthorized,才能使用相册
    
    /*
    PHAuthorizationStatusNotDetermined    未决定
    PHAuthorizationStatusRestricted    受限制
    PHAuthorizationStatusDenied    拒绝
    PHAuthorizationStatusAuthorized    允许
    */
    
    [PHPhotoLibrary authorizationStatus];
    
    
    • 如果用户没有开启授权,可以来个提醒,或者在合适的时机去跳转到授权界面
    +(void)requestAuthorizationIfNotDetermined{
        
        if (IOSVersion >= 8.0) {
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        } else {
            NSURL *privacyUrl = [NSURL URLWithString:@"prefs:root=Privacy&path=PHOTOS"];
            if ([[UIApplication sharedApplication] canOpenURL:privacyUrl]) {
                [[UIApplication sharedApplication] openURL:privacyUrl];
            } else {
                
                UIAlertView *alert =  [[UIAlertView alloc]initWithTitle:@"相册未授权" message:@"请手动开启相册授权" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
                [alert show];
                
            }
        }
        
    }
    
    
    
    

    创建app对应的相册

    先来了解几个类

    PHAssetCollection

    这个类相当于一个照片组,Collection就是集合的意思

    属性

    //The type of the asset collection, such as an album or a moment.
    //相册的类型
    @property(nonatomic, assign, readonly) PHAssetCollectionType assetCollectionType;
    
    //子类型
    @property(nonatomic, assign, readonly) PHAssetCollectionSubtype assetCollectionSubtype;
    
    //估算的相册中的资源(Asset)数量,没什么卵用
    @property(nonatomic, assign, readonly) NSUInteger estimatedAssetCount;
    
    //开始日期
    @property(nonatomic, strong, readonly) NSDate *startDate;
    //结束日期
    @property(nonatomic, strong, readonly) NSDate *endDate;
    
    //粗略估计存放的位置,没什么卵用
    @property(nonatomic, strong, readonly) CLLocation *approximateLocation;
    
    //这个才是最有用的,这个就是所有相册名称的数组,
    @property(nonatomic, strong, readonly) NSArray<NSString *> *localizedLocationNames;
    
    //单个相册名称
    @property(nonatomic, strong, readonly) NSString *localizedTitle;
    
    

    这个框架里要查找某个东西,都是用 fetch xxx,这个规律
    明显

    • 一些常用方法的解释
    这个方法是我们传入一个相册名称的数组, PHFetchOptions,我们的一些描述信息
    + (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(PHFetchOptions *)options;
    
    Snip20170815_1.png

    PHFetchOptions

    这个类就是对要要获取(Fetch)的内容的一个描述,相当于选择的条件整合,这个类就那么几个属性,可以根据需求来定义

    属性

    //描述信息, NSPredicate这个类和SQL语句的用法类似,具体可参见
    http://www.cocoachina.com/ios/20160111/14926.html
    
    @property(nonatomic, strong) NSPredicate *predicate;
    
    //排序类型
    用法如下,按照你要求的排序类型来给出查询结果
    /*
    PHFetchOptions *fetchOptions = [PHFetchOptions new];
    fetchOptions.sortDescriptors = @[
        [NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES],
    ];
    PHFetchResult *fetchResult = [PHAsset fetchAssetsWithOptions:fetchOptions];
    return [fetchResult firstObject];
    */
    @property(nonatomic, strong) NSArray<NSSortDescriptor *> *sortDescriptors;
    
    
    //是否想要包含资源变化的详细信息
    @property(nonatomic, assign) BOOL wantsIncrementalChangeDetails;
    
    
    //每次的查询数量限制
    @property(nonatomic, assign, readwrite) NSUInteger fetchLimit;
    
    //这三个是要包含的资源类型
    @property(nonatomic, assign) BOOL includeAllBurstAssets;
    @property(nonatomic, assign) BOOL includeHiddenAssets;
    @property(nonatomic, assign) PHAssetSourceType includeAssetSourceTypes;
    
    

    下面开始创建对应app名称的一个相册

    
    - (PHAssetCollection *)createdCollection
    {
        // 获得软件名字
        NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString *)kCFBundleNameKey];
        
        // 抓取所有的自定义相册
        PHFetchResult<PHAssetCollection *> *results= [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        
        // 查找当前App对应的自定义相册
        for (PHAssetCollection *collection in results) {
            if ([collection.localizedTitle isEqualToString:title]) {
                return collection;//找到了就返回
            }
        }
        
        /** 当前App对应的自定义相册没有被创建过 **/
        // 创建一个【自定义相册】
        NSError *error = nil;
        __block NSString *createdCollectionID = nil;
        [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
            createdCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
        } error:&error];
        
        if (error) return nil;
        
        // 根据唯一标识获得刚才创建的相册
        return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCollectionID] options:nil].firstObject;
    }
    
    
    

    系统相册的获取方法

    自己封装了一个关于相册的类

    #import <Foundation/Foundation.h>
    #import "YSPhotoKit.h"
    
    @interface YSAssetAlbum : NSObject
    
    @property (nonatomic, strong) NSString *name;        ///< The album name
    @property (nonatomic, assign) NSInteger count;       ///< Count of photos the album contain
    @property (nonatomic, strong) PHFetchResult *result;       ///相当于存储asset的数组
    
    @property (nonatomic, strong) NSArray *models;//所有照片模型
    @property (nonatomic, strong) NSArray *selectedModels;//选中的照片
    @property (nonatomic, assign) NSUInteger selectedCount;//选中的数量
    
    
    + (YSAssetAlbum *)albumWithResult:(PHFetchResult*)result name:(NSString *)name;
    
    
    @end
    
    
    
    //.m文件的实现
    
    #import "YSAssetAlbum.h"
    
    @implementation YSAssetAlbum
    
    + (YSAssetAlbum *)albumWithResult:(PHFetchResult*)result name:(NSString *)name{
        YSAssetAlbum *album = [[YSAssetAlbum alloc]init];
        album.result = result;
        album.name = name;
        
        if ([result isKindOfClass:[PHFetchResult class]]) {
            album.count = result.count;
        }
        
        return album;
    }
    
    
    @end
    
    
    
    
    
    //获得相机胶卷
    -(void)getSmartAlbumAllowVideo:(BOOL)allowVideo AllowPhoto:(BOOL)allowPhoto completion:(void(^)(YSAssetAlbum *model))completion{
        
        __block YSAssetAlbum *album ;
    
        PHFetchOptions *option = [[PHFetchOptions alloc]init];
        
        if (IOSVersion >= 8.0) {
            
            if (!allowVideo) {
                option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
    
            }
            
            if (!allowPhoto) {
                option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
                                    PHAssetMediaTypeVideo];
            }
            
            NSSortDescriptor *sortDescriptors = [NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate];
            
            option.sortDescriptors = @[sortDescriptors];
            
            
            
            PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
            
            for (PHAssetCollection *assetCollection in fetchResult) {
                
                //过滤掉不是相册的对象
                if (![assetCollection isKindOfClass:[PHAssetCollection class]]) {
                    continue;
                }
                
                if ([self isCameraRollAlbum:assetCollection.localizedTitle]) {
                    
                    PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:option];
                    
                    album = [YSAssetAlbum albumWithResult:assetsFetchResult name:assetCollection.localizedTitle];
                    
                    if (completion){
                        completion(album);
                    }
                    
                    break;
                }
                
            }
        
        }
        
    }
    
    
    
    

    总结

    从上面的简单描述可见,查询一个相册内资源的方法是

    1 首先要请求授权 PHPhotoLibrary
    2 然后要创建描述信息 PHFetchOptions
    3 然后用 PHAssetCollection 去fetch xxx ,得到PHFetchResult
    4 接着遍历PHFetchResult,这个类里面存的又都是PHAssetCollection
    5然后用 PHAsset 去fetch xxx ,获取资源得到的又是PHFetchResult *assetsFetchResult
    这个PHFetchResult里面存的是PHAsset,其实PHFetchResult就是一个和数 组一样功能的类

    • 如果我们想要取得某个PHAsset所对应的照片或者视频,又需要用到一个类
      PHImageManager ,这个类是个单列,然后把我们的PHAsset当做参数传入这个类的 request xxxx ForAsset xxx方法中,类似的方法有好几个
      • requestImageForAsset
      • requestImageDataForAsset
      • requestLivePhotoForAsset
      • requestPlayerItemForVideo
      • requestAVAssetForVideo

    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeDefault options:option resultHandler:

    最后查询的结果在resultHandler中回调出来,整个思路就是这样,我自己封装了一些方法,使用方便点,需要的可以去下载

    https://github.com/HongXiuTanXiang/YSphoto

    相关文章

      网友评论

          本文标题:Photo Kit 使用总结

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