PhotoKit:PHObject 获取资产

相关类

2. PHObject
  2.1. PHAsset
  2.2. PHCollection
    2.2.1. PHAssetCollection
    2.2.2. PHCollectionList
  2.R.1. PHFetchResult
  2.R.2. PHFetchOptions

2. PHObject

  • 父类:NSObject

Photos的模型对象(资源assets集合collections)的抽象类。
即,PHObjectPhotos框架的一个基类。

你不应该创建或直接使用这个类的实例。而是应该使用这个类的子类的实例:PHAssetPHAssetCollectionPHCollectionListPHObjectPlaceholder

因为PHObject类实现了- (BOOL)isEqual:(id)object;和对它自己的localIdentifier属性生成@property(readonly) NSUInteger hash;的方法。你可以根据这些方法来使用一些技巧用以跟踪资源集合对象。

1. 识别对象
localIdentifier
//持久标识对象的唯一字符串。

2.1. PHAsset

  • 父类:PHObject

图片库中图像、视频或活动照片的表示形式。
获取资产并开始使用它们。使用在“获取资产”中列出的方法来检索一个或多个PHAsset实例(用于显示或编辑)。
资产只包含元数据。任何给定资产的底层图像或视频数据可能都不会存储在本地设备上。但是,根据您计划如何使用这些数据,您可能不需要下载所有数据。如果需要使用缩略图填充集合视图,则Photos框架可以管理每个资产的下载、生成和缓存缩略图。有关详细信息,请参见PHImageManager
资产对象是不可变的。要编辑资产的元数据(如将其标记为收藏的照片),请在照片库更改块中创建一个PHAssetChangeRequest对象。有关使用更改请求和更改块更新照片库的详细信息,请参阅PHPhotoLibrary

1. 获取资产(Asset)
+ fetchAssetsInAssetCollection:options:
//从指定的asset collection中获取Asset

+ fetchAssetsWithMediaType:options:
//从指定的媒体类型中获取Asset

+ fetchAssetsWithLocalIdentifiers:options:
//从指定的一组惟一标识符中获取Asset

+ fetchKeyAssetsInAssetCollection:options:
//获取指定的asset collection中标记为关键Asset的Asset

+ fetchAssetsWithOptions:
//获取与指定选项匹配的所有Asset

+ fetchAssetsWithBurstIdentifier:options:
//获取指定的burst照片序列标识符的Asset
2. 读取Asset的MetaData
mediaType
//Asset的类型(图片,视频,音频,未知类型)

mediaSubtypes
//Asset的子类型,详情参考PHAssetMediaSubtype

sourceType
//Asset的源类型,详情参考PHAssetSourceType

pixelWidth
//The width, in pixels, of the asset’s image or video data.
pixelHeight
//The height, in pixels, of the asset’s image or video data.
creationDate
//The date and time at which the asset was originally created.
modificationDate
//The date and time at which the asset was last modified.
location
//The location information saved with the asset.
duration
//The duration, in seconds, of the video asset.
favorite
//A Boolean value that indicates whether the user has marked the asset as a favorite.
hidden
//A Boolean value that indicates whether the user has hidden the asset.
3. Displaying an Asset
4. Editing an Asset
5. Working with Burst Photo Assets

2.2. PHCollection

  • 父类:PHObject
    Photos资源的集合和集合列表的抽象超类(父类)。

你不应该创建或直接使用这个类的实例。而是应该使用这个类的两个子类中的一个,PHAssetCollection或PHCollectionList

  • 一个PHAssetCollection对象代表了一个照片或者视频资源的集合,比如说一个相簿,一个时刻,或者是共享相簿。
  • 一个PHCollectionList对象代表了一个包含了其他集合的集合,比如说一个包含许多相簿的文件夹或者一个包含一年所有时刻的集合。

2.2.1. PHAssetCollection

  • 父类:PHCollection

一个照片资源分类的表现形式,例如一个时刻,用户创建的相册或者智能相册。

Photos框架中,集合对象(包括资源集合)不会直接使用它们的成员对象,并且也没有其他的对象来直接使用集合对象。为了获取一个资源集合的成员,应使用PHAsset的类方法,例如+ (PHFetchResult *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(PHFetchOptions *)options;。为了查找资源集合,应使用下面的“获取资源集合”中的方法。

资源集合列表一样,资源集合是不可变的。想要创建、重命名、删除资源集合,或者想要在一个资源集合中添加成员、移除成员、对成员重新排序,应在一个照片库的变化回调中创建一个PHAssetCollectionChangeRequest对象。

1.1.2.1. 获取资源集合

1.1.2.1.1. 查找给定类型和给定子类型的资源集合

如果没有对应的资源集合则返回空的获取结果。

+ (PHFetchResult *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options;
1.1.2.1.1.1. PHAssetCollectionType
typedef NS_ENUM(NSInteger, PHAssetCollectionType) {
    PHAssetCollectionTypeAlbum      = 1, // 在 照片 应用中创建的相簿或者通过iTunes同步的在iOS设备上显示的相簿
    PHAssetCollectionTypeSmartAlbum = 2, // 照片 应用中内置的相簿
    PHAssetCollectionTypeMoment     = 3, // 照片 应用中的 时刻
} PHOTOS_ENUM_AVAILABLE_IOS_TVOS(8_0, 10_0);
1.1.2.1.1.2. PHAssetCollectionSubtype
typedef NS_ENUM(NSInteger, PHAssetCollectionSubtype) {
    // PHAssetCollectionTypeAlbum regular subtypes
    PHAssetCollectionSubtypeAlbumRegular         = 2, // 在 相册 应用中创建的相簿
    PHAssetCollectionSubtypeAlbumSyncedEvent     = 3, // 从iPhone中同步到设备的 事件 
    PHAssetCollectionSubtypeAlbumSyncedFaces     = 4, // 从iPhone中同步到设备的 面孔(人物)
    PHAssetCollectionSubtypeAlbumSyncedAlbum     = 5, // 从iPhone中同步到设备的相簿
    PHAssetCollectionSubtypeAlbumImported        = 6, // 从相机或者外部存储设备中导入的相簿
    // PHAssetCollectionTypeAlbum shared subtypes
    PHAssetCollectionSubtypeAlbumMyPhotoStream   = 100, // 用户自己的iCloud照片流
    PHAssetCollectionSubtypeAlbumCloudShared     = 101, // 一个iCloud共享照片流
    // PHAssetCollectionTypeSmartAlbum subtypes
    PHAssetCollectionSubtypeSmartAlbumGeneric    = 200, // 没有指定子类型的智能相簿
    PHAssetCollectionSubtypeSmartAlbumPanoramas  = 201, // 包含了照片库中所有全景照片的智能相簿——全景照片
    PHAssetCollectionSubtypeSmartAlbumVideos     = 202, // 包含了照片库中所有视频的智能相簿——视频
    PHAssetCollectionSubtypeSmartAlbumFavorites  = 203, // 包含了照片库中所有用户标记为喜欢的资源的智能相簿——个人收藏
    PHAssetCollectionSubtypeSmartAlbumTimelapses = 204, // 包含了照片库中所有延时视频的智能相簿——慢动作
    PHAssetCollectionSubtypeSmartAlbumAllHidden  = 205, // 包含了 照片 应用中所有从 时刻 中隐藏的资源的智能相簿——
    PHAssetCollectionSubtypeSmartAlbumRecentlyAdded = 206, // 包含了所有最近添加到图片库的资源的智能相簿——
    PHAssetCollectionSubtypeSmartAlbumBursts     = 207, // 包含了所有连拍的智能相簿——连拍快照
    PHAssetCollectionSubtypeSmartAlbumSlomoVideos = 208, // 包含了 照片 应用中所有慢动作视频的智能相簿——慢动作
    PHAssetCollectionSubtypeSmartAlbumUserLibrary = 209, // 包含了所有用户自己的图库的资源的智能相簿(而不是来自于iCloud共享流的资源)
    PHAssetCollectionSubtypeSmartAlbumSelfPortraits PHOTOS_AVAILABLE_IOS_TVOS(9_0, 10_0) = 210, // 包含了所有使用前置摄像头拍摄的资源的智能相册——自拍
    PHAssetCollectionSubtypeSmartAlbumScreenshots PHOTOS_AVAILABLE_IOS_TVOS(9_0, 10_0) = 211, // 包含了所有使用屏幕截图的资源的智能相册——屏幕快照
    PHAssetCollectionSubtypeSmartAlbumDepthEffect PHOTOS_AVAILABLE_IOS_TVOS(10_2, 10_1) = 212, // 包含了所有兼容设备上使用景深效果拍摄的资源的智能相册
    PHAssetCollectionSubtypeSmartAlbumLivePhotos PHOTOS_AVAILABLE_IOS_TVOS(10_3, 10_2) = 213, // 包含了所有Live Photo的智能相册——Live Photo
    // Used for fetching, if you don't care about the exact subtype
    PHAssetCollectionSubtypeAny = NSIntegerMax // 所有可能的子类型
} PHOTOS_ENUM_AVAILABLE_IOS_TVOS(8_0, 10_0);
1.1.2.1.2. 通过(localIdentifier属性)查找对应的资源集合
+ (PHFetchResult *)fetchAssetCollectionsWithLocalIdentifiers:(NSArray *)identifiers options:(nullable PHFetchOptions *)options;

通过给定的唯一标识(localIdentifier属性)查找对应的资源集合。如果没有对应的资源集合则返回空的获取结果。

1.1.2.2. 读取资源集合的数据

1.1.2.2.1. assetCollectionType
@property (nonatomic, assign, readonly) PHAssetCollectionType assetCollectionType;

资源集合的类型,例如一个相簿或者一个时刻。

1.1.2.2.2. assetCollectionSubtype
@property (nonatomic, assign, readonly) PHAssetCollectionSubtype assetCollectionSubtype;

资源集合的子类型。使用子类型在同类型的集合之间进行细微区别。

1.1.2.2.3. estimatedAssetCount
@property (nonatomic, assign, readonly) NSUInteger estimatedAssetCount;

资源集合中资源的估算数量。
这个数量可能与当前集合中的资源数不一样。想要获得最新的资源数量请使用+ (PHFetchResult*)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(PHFetchOptions *)options;获取集合中的资源然后读取获取结果中的count属性。
如果对于某个集合来说资源数量是不可用的属性,则则个属性的值是NSNotFound。

1.1.2.2.4. startDate
@property (nonatomic, strong, readonly, nullable) NSDate *startDate;

资源集合中所有资源中最早的一个的创建日期。
这个属性仅在资源集合的类型为PHAssetCollectionTypeMoment时有效。对于其他类型,这个属性的值为nil

1.1.2.2.5. endDate
@property (nonatomic, strong, readonly, nullable) NSDate *endDate;

资源集合中所有资源中距离现在时间最近的一个的创建日期。
这个属性仅在资源集合的类型为PHAssetCollectionTypeMoment时有效。对于其他类型,这个属性的值为nil

1.1.2.2.6. approximateLocation
@property (nonatomic, strong, readonly, nullable) CLLocation *approximateLocation;

资源集合中所有资源的定位地点。
照片应用会在拍摄时自动创建对应的时刻和地点的分组,同一时刻照片资源的地点应该非常接近,所以这个属性表示的是一个大致的共有的定位地点。
这个属性仅在资源集合的类型为PHAssetCollectionTypeMoment时有效。对于其他类型,这个属性的值为nil。

1.1.2.2.7. localizedLocationNames
@property (nonatomic, strong, readonly) NSArray *localizedLocationNames;

资源集合中所有资源的定位地点的名称。
照片应用会在拍摄时自动创建对应的时刻和地点的分组,同一时刻照片资源的地点应该非常接近,但有可能有多个地点名称,所以这个属性表示的是一个定位地点名称组成的数组。
这个属性仅在资源集合的类型为PHAssetCollectionTypeMoment时有效。对于其他类型,这个属性的值为nil。


2.2.1. PHCollectionList

  • 父类:PHCollection

包含了一组Photos资源集合的表现形式,例如一个时刻中的“年”或者用户创建的相簿文件夹。

Photos框架中,集合对象(包括资源集合)不能直接引用它们自己内部的成员对象,并且也没有其他的对象能够直接引用集合对象。想要调用一个集合列表中的成员,请使用PHCollection的类方法获取,例如+ (PHFetchResult *)fetchCollectionsInCollectionList:(PHCollectionList *)collectionList options:(PHFetchOptions *)options;。想要在集合列表的顶层(例如一个没有上级文件夹的相簿文件夹)中查找一个对象,请使用+ (PHFetchResult *)fetchTopLevelUserCollectionsWithOptions:(PHFetchOptions *)options;方法。

资源以及资源集合一样,集合列表也是不可以被修改的。想要创建、重命名、删除一个集合列表,或者想要添加、删除、重置集合列表中的内容,请在PHPhotoLibrary中的更改回调中创建一个PHCollectionListChangeRequest对象。


2.R.1. PHFetchResult

  • 父类:NSObject

从一个Photos的获取方法中返回的有序的资源或者集合的列表。

当你使用PHAsset、PHCollection、PHAssetCollection和PHCollectionList类的方法来获取对象,Photos会提供一个PHFetchResult类的一个对象作为结果。你访问结果中的内容可以像使用NSArray类的方法获取内容一样来获取PHFetchResult中的内容。与NSArray对象不同的是,一个PHFetchResult对象中的内容是动态加载的,如果你需要一些内容它才会去照片库中去获取对应的内容,这可以在处理大量的结果的时候提供一个最佳的性能。

获取结果对它包含的内容提供线程安全的访问。在一次获取之后,获取结果count属性值是一个常量,获取结果中包含的所有对象会保持相同的localIdentifier属性值。(为了得到一次获取的内容更新,需要为共享的PHPhotoLibrary对象注册一个监听变化的监听器。)

获取结果会缓存它里面的内容,会存储最近访问过的大多数内容。由于这些对象之外的其他的对象不会被缓存,所以访问未被缓存的对象需要重新获取这些对象。这个过程可能会导致之前在这些对象中获取到的一些值的改变。

1. 查询获取结果
- containsObject:
//返回获取结果中是否存在指定的对象
count
//获取结果中的对象数量
- countOfAssetsWithMediaType:
//返回指定类型的获取结果中的资产数量
firstObject
//第一个对象
lastObject
//最后一个对象
- objectAtIndex:
//返回位于指定索引处的对象
- objectAtIndexedSubscript:
//返回位于指定索引处的对象
- objectsAtIndexes:
//返回一个数组,该数组在指定索引集中的索引处包含fetch结果中的对象。
  1. containsObject
    查询给定的对象是否在获取结果中。
    这个方法会遍历获取结果,对其中的每一个对象使用- (BOOL)isEqual:(id)object;方法进行比对。
  2. countOfAssetsWithMediaType
    返回获取结果中指定类型的资源的数量。
    第一次调用这个方法Photos会枚举每一个对象进行匹配,并将匹配的结果数量进行缓存,之后所有的该方法的调用都只返回缓存的结果。
    这个方法只会记录PHAsset类的对象的数量,如果获取结果中只有PHAssetCollection类的对象或PHCollectionList类的对象,则该方法会返回0。
2. 在获取结果中查找对象
- indexOfObject:
//Returns the lowest index whose corresponding object in the fetch result is equal to the specified object.

- indexOfObject:inRange:
//Returns the lowest index within the specified range whose corresponding object in the fetch result is equal to the specified object.
3. 在获取结果中执行对对象的操作
- enumerateObjectsAtIndexes:options:usingBlock:
//Executes the specified block using the objects in the fetch result at the specified indexes.

- enumerateObjectsUsingBlock:
//快速枚举获取结果中的所有对象
/**
  该方法是顺序枚举,并且是同步方法,会阻塞主线程。
  @block - 快速枚举的操作
    @obj ObjectType - 被枚举的对象
    @idx NSUInteger - 被枚举的对象的索引
    @stop BOOL - 在block中设置为YES将会取消当前对获取结果的处理。
*/
- (void)enumerateObjectsUsingBlock:
(
  void (^)
    (ObjectType obj, 
    NSUInteger idx, 
    BOOL *stop)
)block;

- enumerateObjectsWithOptions:usingBlock:
//Executes the specified block using each object in the fetch result.

2.R.2. PHFetchOptions

对asset和collection返回结果进行筛选、排序和管理的选项。
使用PHAssetPHCollectionPHAssetCollectionPHCollectionList类上的类方法来获取资产或集合,同时生成一个PHFetchResult对象(包含所请求资产或集合对象)。你指定的选项控制取回结果包含哪些对象和这些对象是如何排列的,以及Photos如何通知你的应用程序取回结果的变化。
Photos只支持predicatesortDescriptors属性的一组受限制的键。可用键的集合取决于你使用哪个类来获取资产或集合。
每个类支持的键的列表见下表。

使用的类 支持的Key
PHAsset SELF, localIdentifier, creationDate, modificationDate, mediaType, mediaSubtypes, duration, pixelWidth, pixelHeight, favorite (or isFavorite), hidden (or isHidden), burstIdentifier
PHAssetCollection SELF, localIdentifier, localizedTitle (or title), startDate, endDate, estimatedAssetCount
PHCollectionList SELF, localIdentifier, localizedTitle (or title), startDate, endDate
PHCollection (可以是PHCollectionList和 PHAssetCollection混合对象) SELF, localIdentifier, localizedTitle (or title), startDate, endDate

I.1. 获取对象和请求更改

根据指定的查询获取assets, asset collections和collection lists。
模型类PHAssetPHAssetCollectionPHCollectionList的实例分别表示用户在“照片”APP中使用的项目:

  • assets:图像、视频和实况照片
  • asset collections:相册或瞬间
  • collection lists:相册文件夹或瞬间集群

这些类的实例是只读和不可变的,并且只包含元数据。使用这些类获取一组匹配指定查询的对象。

向共享照片库提交更改请求
获取您感兴趣的资产和集合,并使用这些对象获取您需要引用或编辑的原始数据。要进行更改,请创建更改请求对象并显式地将它们提交到共享PHPhotoLibrary对象。这种体系结构使多个线程或多个APP和APP扩展对相同资产进行处理变得简单、安全和高效。

处理特殊的资产
PhotoKit支持许多“照片”APP的功能,可以直接使用用户的照片库。例如,实况照片是带有附加数据的特殊资产,您的应用程序可以以不同的方式显示这些数据,比如视频或帧序列。
使用PHCollectionList类查找“照片”APP中与Moments层次结构对应的资产。集合列表是只读的、不可变的,并且只包含元数据。使用PHAsset类来识别burst照片、实况照片、全景照片和高帧率视频。

I.2. Editing Asset Content


A. DEMO

A.1. DEMO1

获取相薄列表

-(void)getAssetCollection{
    NSMutableArray * dataArray=@[].mutableCopy;
    
    /**
     查找给定类型和给定子类型的资源集合
     PHAssetCollectionTypeAlbum - 在[照片]APP中创建的相簿或者通过iTunes同步的在iOS设备上显示的相簿
     PHAssetCollectionSubtypeAlbumRegular - 在[相册]APP中创建的相簿
     */
    PHFetchResult * collectionResult = [PHAssetCollection fetchAssetCollectionsWithType:_type subtype:_subType options:nil];
    if (collectionResult.count == 0) {
        return;
    }
    /**
     快速枚举获取结果中的所有对象
     ^() block - 快速枚举的操作
     obj ObjectType - 被枚举的对象
     idx NSUInteger - 被枚举的对象的索引
     stop BOOL - 在block中设置为YES将会取消当前对获取结果的处理。
     */
    [collectionResult enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        AssetCollection * ac=[AssetCollection new];
        ac.title=obj.localizedTitle;
        ac.collectionDescription=@"";
        
        /**
         从指定的资源集合中检索资源
         obj - PHAssetCollection 资源集合
         options - PHFetchOptions 检索选项
         */
        NSLog(@"===============");
        NSLog(@"Local Identifier:%@",obj.localIdentifier);
        NSLog(@"Localized Title:%@",obj.localizedTitle);
        NSLog(@"Asset Collection Type:%ld", obj.assetCollectionType);
        NSLog(@"Asset Collection Sub Type:%ld", obj.assetCollectionSubtype);
        NSLog(@"Astimated Asset Count:%ld", obj.estimatedAssetCount);
        NSLog(@"Start Date:%@", obj.startDate);
        NSLog(@"End Date:%@", obj.endDate);
        NSLog(@"Approximate Location:%@", obj.approximateLocation);
        NSLog(@"Localized Location Names:%@", obj.localizedLocationNames);
        
        PHFetchResult * assetResult = [PHAsset fetchAssetsInAssetCollection:obj options:nil];
        NSLog(@"ID:%ld", idx);
        NSLog(@"Count:%ld", assetResult.count);
        NSLog(@"Image Count:%ld",[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeImage]);
        NSLog(@"Video Count:%ld",[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeVideo]);
        NSLog(@"Audio Count:%ld",[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeAudio]);
        
        ac.collectionDescription=[NSString stringWithFormat:@"文件数量:%ld(图片:%ld,视频:%ld,音频:%ld)", assetResult.count ,[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeImage] ,[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeVideo],[assetResult countOfAssetsWithMediaType:PHAssetMediaTypeAudio]];
        
        
        [dataArray addObject:ac];
        
    }];
    _dataSource=dataArray.copy;
}
代码

https://github.com/DavidJi80/iosCodeUI
v0.13.1

A.2. DEMO1

获取特定相薄的Asset资源

-(void)fetchAssetByIdentifier{
    /**
     通过localIdentifier获取PHAssetCollection
     identifiers - localIdentifier数组
     options - 过滤选项
     */
    PHFetchResult * collectionResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[_localIdentifier] options:nil];
    if (collectionResult.count == 0) {
        return;
    }
    //取出第一个PHAssetCollection对象
    PHAssetCollection * ac=[collectionResult firstObject];
    self.navigationItem.title=ac.localizedTitle;
    //从指定AssetCollection中获取Asset
    PHFetchResult * assetResult = [PHAsset fetchAssetsInAssetCollection:ac options:nil];
    //在Asset结果集中快速枚举
    [assetResult enumerateObjectsUsingBlock:^(PHAsset * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"===========%ld=========",idx);
        NSLog(@"mediaType:%ld",obj.mediaType);
        NSLog(@"mediaSubtypes:%ld",obj.mediaSubtypes);
        NSLog(@"sourceType:%ld",obj.sourceType);
        NSLog(@"creationDate:%@",obj.creationDate);
        NSLog(@"location:%@",obj.location);
        
        //获取Asset的底层资源
        NSArray * ars=[PHAssetResource assetResourcesForAsset:obj];
        for (PHAssetResource * ar in ars) {
            NSLog(@"type - %ld",ar.type);
            NSLog(@"originalFilename - %@", ar.originalFilename);
            NSLog(@"uniformTypeIdentifier - %@", ar.uniformTypeIdentifier);
            NSLog(@"assetLocalIdentifier - %@", ar.assetLocalIdentifier);
        }
        
        if (obj.mediaType==PHAssetMediaTypeImage){
            [[PHCachingImageManager defaultManager] requestImageForAsset:obj targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                    self.imageView.image=result;
            }];
            
        }else if (obj.mediaType==PHAssetMediaTypeVideo){
            [[PHImageManager defaultManager]requestAVAssetForVideo:obj options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
                NSString* sandboxExtensionTokenKey = info[@"PHImageFileSandboxExtensionTokenKey"];
                NSArray* arr = [sandboxExtensionTokenKey componentsSeparatedByString:@";"];
                NSString* filePath = [arr.lastObject substringFromIndex:9];
                NSLog(@"#############%@",filePath);
            }];
        }
    }];
}
代码

https://github.com/DavidJi80/iosCodeUI
v0.13.2

参考

https://www.jianshu.com/p/119e5df0a03e
https://www.jianshu.com/p/da03e3061aad
https://www.jianshu.com/p/020775e39da4
https://www.jianshu.com/p/3612365d6494
https://www.jianshu.com/p/3ac116ffffcc
https://www.jianshu.com/p/c5fe835bb0fb
https://www.jianshu.com/p/ce48b0e743a8
https://www.jianshu.com/p/cf0816e93197
https://www.jianshu.com/p/0ff787121ebc
https://developer.apple.com/documentation/photokit/phfetchoptions
https://developer.apple.com/documentation/photokit/phfetchresult?language=objc
https://www.jianshu.com/p/fdf6d8d6c946

你可能感兴趣的:(PhotoKit:PHObject 获取资产)