1. Model
PHAsset 、PHAssetCollection、PHCollectionList 是Photos框架中的模型類,PHAsset類是數(shù)據(jù)模型抬闯,描述圖片或者視頻文件數(shù)據(jù);PHAssetCollection描述了包括相冊影钉、moments画髓、智能相冊以及共享照片流等一系列圖片或者視頻文件的集合的元數(shù)據(jù);PHCollectionList是一組資源集合平委,可能是一組Assets奈虾,也可能是一組collection。 它們關(guān)系如下圖:
1.1 PHAsset
PHAsset是iOS8平臺的新接口廉赔,存儲獲取圖片和視頻文件的元數(shù)據(jù)
肉微,這些圖片和視頻文件可能在手機本地,也可能在iCloud蜡塌。相當(dāng)于以前的 ALAsset接口,但比起ALAsset,PhotoKit 提供了額外的關(guān)于用戶資源的元數(shù)據(jù)碉纳,而這些數(shù)據(jù)在以前使用 ALAssetsLibrary 框架中是沒有辦法訪問,或者很難訪問到馏艾。
它有幾個要點:
- 需要用PHAsset的一些fetchAssets...系列類方法獲取到劳曹,你想要拿到的照片的PHAsset對象奴愉。
- PHAsset 對象只包含元數(shù)據(jù),image或者video數(shù)據(jù)需要用PHImageManager加載铁孵。
- PHAsset對象的元數(shù)據(jù)是不可變的锭硼,修改元數(shù)據(jù)需要借助 PHAssetChangeRequest
它有幾個重要屬性:
-
mediaType
:資源類型,圖片或者音頻或視頻
Paste_Image.png -
mediaSubtypes
:圖片又包含全景圖(Panorama)、HDR圖片蜕劝、屏幕截圖檀头、livePhoto .live photo 加3Dtouch效果太贊! [視頻鏈接].我們可以使用照片資源的 mediaSubtypes 屬性驗證資源庫中的圖像在捕捉時是否開啟了 HDR岖沛,拍攝時是否使用了相機應(yīng)用的全景模式.(http://www.macworld.com/article/2988585/apple-phone/how-to-get-started-with-3d-touch-live-photos-and-4k-video-on-the-iphone-6s.html)Paste_Image.png Creation date
Location
-
Favorite
布爾值暑始,用戶是否標(biāo)記資源為"收藏",我們平時瀏覽照片或視頻婴削,在下方點??就表示收藏這張圖廊镜。 -
hidden
要驗證一個資源是否被用戶標(biāo)記為收被隱藏,只要檢查 PHAsset 實例的 hidden 屬性即可馆蠕。 -
sourceType
: 資源可以來源自用戶相冊期升、iCloud惊奇、iTunes同步
Paste_Image.png -
representsBurst
和burstSelectionTypes
: 對于一個資源互躬,如果其 PHAsset 的 representsBurst 屬性為 true,則表示這個資源是一系列連拍照片中的代表照片 (多張照片是在用戶按住快門時拍攝的)颂郎。它還有一個屬性是 burstIdentifier吼渡,如果想要獲取連拍照片中的剩余的其他照片,可以通過將這個值傳入 fetchAssetsWithBurstIdentifier(...) 方法來獲取乓序。用戶可以在連拍的照片中做標(biāo)記寺酪;此外,系統(tǒng)也會自動用各種試探來標(biāo)記用戶可能會選擇的潛在代表照片替劈。這個元數(shù)據(jù)是可以通過 PHAsset 的 burstSelectionTypes 屬性來訪問寄雀。這個屬性是用三個常量組成的位掩碼:.UserPick 表示用戶手動標(biāo)記的資源,.AutoPick 表示用戶可能標(biāo)記的潛在資源陨献,.None 表示沒有標(biāo)記的資源盒犹。
我模擬器相冊中某張圖片:
<PHAsset: 0x7f8293659e20> B84E8479-475C-4727-A4A4-B77AA9980897/L0/001 mediaType=1/0, sourceType=1, (4288x2848), creationDate=2009-10-09 21:09:20 +0000, location=0, hidden=0, favorite=0
localIdentifier
Photos 框架中的根類PHObject只有一個公開接口localIdentifier,是對象唯一唯一標(biāo)志符.PHObject實現(xiàn)了-isEqual 和-hash方法.可以直接使用localIdentifier屬性對PHObject及其子類對象進行對比是否同一個對象种柑。
在我的模擬器中“最近刪除”這個相冊的localIdentifier為72053882-BF20-4D4A-B1A5-03D1DDAE1707/L0/040
1.2 PHAssetCollection
PHAssetCollection是一組有序的資源集合,包括相冊痪蝇、moments、智能相冊以及共享照片流.
它的重要屬性 辆飘;
- assetCollectionType 資源集合類型龄捡,比如相冊或者“時刻”相冊
typedef NS_ENUM(NSInteger, PHAssetCollectionType) {
PHAssetCollectionTypeAlbum = 1,
PHAssetCollectionTypeSmartAlbum = 2,
PHAssetCollectionTypeMoment = 3,
} NS_ENUM_AVAILABLE_IOS(8_0);
- assetCollectionSubtype 子類型
enum PHAssetCollectionType : Int {
case Album //從 iTunes 同步來的相冊卓嫂,以及用戶在 Photos 中自己建立的相冊
case SmartAlbum //經(jīng)由相機得來的相冊
case Moment //Photos 為我們自動生成的時間分組的相冊
}
enum PHAssetCollectionSubtype : Int {
case AlbumRegular //用戶在 Photos 中創(chuàng)建的相冊
case AlbumSyncedEvent //使用 iTunes 從 Photos 照片庫或者 iPhoto 照片庫同步過來的事件。然而聘殖,在iTunes 12 以及iOS 9.0 beta4上晨雳,選用該類型沒法獲取同步的事件相冊行瑞,而必須使用AlbumSyncedAlbum。
case AlbumSyncedFaces //使用 iTunes 從 Photos 照片庫或者 iPhoto 照片庫同步的人物相冊餐禁。
case AlbumSyncedAlbum //做了 AlbumSyncedEvent 應(yīng)該做的事
case AlbumImported //從相機或是外部存儲導(dǎo)入的相冊蘑辑,完全沒有這方面的使用經(jīng)驗,沒法驗證坠宴。
case AlbumMyPhotoStream //用戶的 iCloud 照片流
case AlbumCloudShared //用戶使用 iCloud 共享的相冊
case SmartAlbumGeneric //文檔解釋為非特殊類型的相冊洋魂,主要包括從 iPhoto 同步過來的相冊。
case SmartAlbumPanoramas //相機拍攝的全景照片
case SmartAlbumVideos //相機拍攝的視頻
case SmartAlbumFavorites //收藏文件夾
case SmartAlbumTimelapses //延時視頻文件夾喜鼓,同時也會出現(xiàn)在視頻文件夾中
case SmartAlbumAllHidden //包含隱藏照片或視頻的文件夾
case SmartAlbumRecentlyAdded //相機近期拍攝的照片或視頻
case SmartAlbumBursts //連拍模式拍攝的照片
case SmartAlbumUserLibrary //這個命名最神奇了副砍,就是相機相冊,所有相機拍攝的照片或視頻都會出現(xiàn)在該相冊中庄岖,而且使用其他應(yīng)用保存的照片也會出現(xiàn)在這里豁翎。
case Any //包含所有類型
}
startDate
endDate
estimatedAssetCount :估算的asset數(shù)量,不精確
我模擬器 智能相冊里隅忿,“最近刪除”這個相冊的對象信息
<PHAssetCollection: 0x7f82951bd640> 72053882-BF20-4D4A-B1A5-03D1DDAE1707/L0/040 Recently Deleted assetCollectionType=2/1000000201
1.3 PHCollectionList
一組有序的資源集合的集合心剥,暫時還沒用過。幾個重要屬性:
- collectionListType
- collectionListSubtype
- startDate
- endDate
2. 獲取模型數(shù)據(jù)
PHAsset 背桐、PHCollection优烧、PHCollectionList有一系列類方法可供我們訪問資源的元數(shù)據(jù)
2.1 比如PHAsset提供了一系列獲取PHAsset對象的方法
+ fetchAssetsInAssetCollection:options:
+ fetchAssetsWithMediaType:options:
+ fetchAssetsWithLocalIdentifiers:options:
+ fetchKeyAssetsInAssetCollection:options:
+ fetchAssetsWithOptions:
+ fetchAssetsWithBurstIdentifier:options:
+ fetchAssetsWithALAssetURLs:options:
其中fetchAssetsInAssetCollection:options:方法可以獲取資源集合中的所有asset對象。每個方法中的 PHFetchOptions參數(shù)链峭,是獲取asset對象的一些配置畦娄,我們可以設(shè)置獲取asset的條件,比如獲取哪種資源,如何分類弊仪。獲取的時候熙卡,如果該參數(shù)為空,則使用系統(tǒng)的默認(rèn)值励饵,當(dāng)我們調(diào)用如上所示方法獲取時驳癌,可以直接傳nil。
例子:
PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
// 按圖片生成時間排序
allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
// 獲取圖片
PHFetchResult *allPhotos = [PHAsset fetchAssetsWithOptions:allPhotosOptions];
// 獲取智能相冊
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 獲取用戶創(chuàng)建的相冊
PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
2.2 PHFetchOptions
-
predicate : 做選擇的約束條件役听。比如颓鲜,只獲取圖片,不獲取視頻禾嫉。指定 PHAssetMediaType為image.
// swift:
options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
```
- sortDescriptors 可指定字段用來對獲取結(jié)果進行排序
- includeHiddenAssets 獲取結(jié)果是否包括被隱藏的資源
- includeAllBurstAssets 獲取結(jié)果是否包括連拍資源
PHFetchOptions *options = [[PHFetchOptions alloc] init];
options.wantsIncrementalChangeDetails = YES;
options.includeAllBurstAssets = YES;
options.includeHiddenAssets = YES;
// 只取圖片
options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d",PHAssetMediaTypeImage];
// 按時間排序
options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
PHFetchResult *albums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumAllHidden options:nil];
2.3 PHFetchResult
類似數(shù)組灾杰,存儲獲取到asset對象集合。
- 同步快速獲取結(jié)果,
- 即使結(jié)果集很大熙参,框架也能保證獲取速度. 因為它不會一次性將所有結(jié)果放進內(nèi)存艳吠,而是按需批量加載
- 可以用類似 NSArray 的接口來訪問PHFetchResult結(jié)果內(nèi)的集合。
比如 :
PHCollection *collection = smartAlbums[n];
3. 資源對象的增刪改
上面PHAsset PHAssetCollection PHCollectionList對象都是不可變的孽椰。那么我們?nèi)绾螌崿F(xiàn)資源增刪改呢昭娩?要借助 request API :
比如:這段代碼用來修改一張圖片的資源屬性:是否被收藏凛篙。
// 創(chuàng)建
request = [PHAssetChangeRequest creationRequestForAssetFromImage:image]
- (void)toggleFavoriteForAsset:(PHAsset *)asset {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// 改變
PHAssetChangeRequest *request = [PHAssetChangeRequest changeRequestForAsset:asset];
request.favorite = !asset.favorite;
} completionHandler:^(BOOL success, NSError *error) {
NSLog(@"Finished updating asset. %@", (success ? @"Success." : error));
}];
}
(1) 創(chuàng)建PHAssetChangeRequest對象。想要修改資源栏渺,需要創(chuàng)建一個 PHAssetChangeRequest 呛梆。然后你就可以修改創(chuàng)建創(chuàng)建日期,資源位置磕诊,以及是否將隱藏資源填物,是否將資源看做用戶收藏等。此外霎终,你還可以從用戶的庫里刪除資源滞磺。類似地,若要修改資源集合或集合列表莱褒,需要創(chuàng)建一個 PHAssetCollectionChangeRequest 或 PHCollectionListChangeRequest對象击困。然后你就可以修改集合標(biāo)題,添加或刪除集合成員广凸,或者完全刪除集合阅茶。
(2) 操作的請求都要求在PHPhotoLibrary的performChanges的changeBlock中執(zhí)行
(3)如果有更新UI操作,需要遵守PHPhotoLibraryChangeObserver
協(xié)議,實現(xiàn)photoLibraryDidChange(changeInfo: PHChange!)方法.在photoLibraryDidChange中進行UI更新操作谅海。
比如脸哀,下面2段代碼用來向冊中新增一張圖片:
// 為image對象生成PHAsset對象,并加入collection
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
if (self.assetCollection) {
PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.assetCollection];
[assetCollectionChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
}
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error creating asset: %@", error);
}
}];
創(chuàng)建一個新資源只要用 creationRequestForAssetFromXXX(...)
工廠方法胁赢,來創(chuàng)建變化請求企蹭,并傳入資源圖像數(shù)據(jù) (或一個 URL)白筹。如果你需要對新建的資源做額外的修改智末,你可以用創(chuàng)建變化請求的placeholderForCreatedAsset屬性。它會返回一個可用的 placeholder 來代替“真實的” PHAsset 引用.
// PHPhotoLibraryChangeObserver協(xié)議的方法徒河,更新相冊UI
- (void)photoLibraryDidChange:(PHChange *)changeInstance {
// Check if there are changes to the assets we are showing.
PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults];
if (collectionChanges == nil) {
return;
}
/*
Change notifications may be made on a background queue. Re-dispatch to the
main queue before acting on the change as we'll be updating the UI.
*/
dispatch_async(dispatch_get_main_queue(), ^{
// Get the new fetch result.
self.assetsFetchResults = [collectionChanges fetchResultAfterChanges];
UICollectionView *collectionView = self.collectionView;
if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) {
// Reload the collection view if the incremental diffs are not available
[collectionView reloadData];
} else {
/*
Tell the collection view to animate insertions and deletions if we
have incremental diffs.
*/
[collectionView performBatchUpdates:^{
NSIndexSet *removedIndexes = [collectionChanges removedIndexes];
if ([removedIndexes count] > 0) {
[collectionView deleteItemsAtIndexPaths:[removedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes];
if ([insertedIndexes count] > 0) {
[collectionView insertItemsAtIndexPaths:[insertedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
NSIndexSet *changedIndexes = [collectionChanges changedIndexes];
if ([changedIndexes count] > 0) {
[collectionView reloadItemsAtIndexPaths:[changedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
} completion:NULL];
}
[self resetCachedAssets];
});
}
3.1 PHPhotoLibrary
系統(tǒng)中PHPhotoLibrary單例對象 是用來維護用戶照片庫系馆。當(dāng)我們需要編輯資源對象元數(shù)據(jù)、資源內(nèi)容顽照、或者插入新的資源對象等由蘑,都可以借助通過PHPhotoLibrary單例對象執(zhí)行block,block中創(chuàng)建我們指定的請求對象(比如PHAssetChangeRequest,PHAssetCollectionChangeRequest, PHCollectionListChangeRequest的對象)代兵。photoLibraryDidChange(changeInfo: PHChange!)中進行.
3.2 協(xié)議PHPhotoLibraryChangeObserver
PHPhotoLibraryChangeObserver協(xié)議能讓我們知道照片相冊庫中的改變尼酿。Photos會發(fā)送系統(tǒng)圖片改變的消息,我們可以遵守PHPhotoLibraryChangeObserver協(xié)議植影,并通過 PHPhotoLibrary的registerChangeObserver方法將對象注冊為觀察者裳擎,時時接收照片改變的消息。
3.3 PHChange
PHphoto框架會提供給我們PHChange對象思币,我們可以調(diào)用changeDetailsForObject或者changeDetailsForFetchResult 方法鹿响,它返回給我們一個PHObjectChangeDetails對象羡微,是對最新的照片實體對象的引用,可以告訴我們對象的圖像數(shù)據(jù)是否曾變化過惶我、對象是否曾被刪除過妈倔。
4.請求圖片和視頻數(shù)據(jù)
4.1 PHImageManager
PHImageManager在框架中是個單例對象,用[PHImageManager defaultManager]
獲取,它提供了加載圖片和視頻的方法绸贡。
比如:圖像請求是通過 requestImageForAsset(...) 方法派發(fā)的盯蝴。
這些方法的參數(shù):
- 一個 PHAsset對象,
- PHImageRequestOptions 參數(shù)對象:可以設(shè)置返回圖像的大小和圖像的其它可選項
- 結(jié)果回調(diào) (result handler)听怕。
請求圖片
- requestImageForAsset:targetSize:contentMode:options:resultHandler:
- requestImageDataForAsset:options:resultHandler:
請求視頻
- requestPlayerItemForVideo:options:resultHandler:
- requestExportSessionForVideo:options:exportPreset:resultHandler:
- requestAVAssetForVideo:options:resultHandler:
默認(rèn)情況下结洼,這些API是異步執(zhí)行,但是我們可以通過options參數(shù)中的synchronous屬性叉跛,設(shè)置為同步執(zhí)行松忍,這些方法會阻塞當(dāng)前調(diào)用線程直到下載完成或者發(fā)生錯誤。
4.2 請求圖片
//加載 160X160 像素的圖片
[manager requestImageForAsset:photo
targetSize:CGSizeMake(160,160)
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
[cell setImage:result];
} else {
... }
}];
targetSize
: 返回圖片的尺寸
contentMode
:決定了照片應(yīng)該以按比例縮放還是按比例填充的方式放到目標(biāo)大小內(nèi)筷厘。
options
: PHImageRequestOptions類用于定制請求鸣峭。上面的方法返回指定尺寸的圖像,如果你僅僅指定必要的參數(shù)而沒有對 options 進行配置的話酥艳,返回的圖像尺寸將會是原始圖像的尺寸摊溶。或者充石,你指定的尺寸很小莫换,這時候會按照你的要求來返回接近該尺寸的圖像。
4.2.1 PHImageRequestOptions有以下幾個重要的屬性:
synchronous
: 指定請求是否同步執(zhí)行骤铃。
resizeMode
: 對請求的圖像怎樣縮放拉岁。有三種選擇:None,不縮放惰爬;Fast喊暖,盡快地提供接近或稍微大于要求的尺寸;Exact撕瞧,精準(zhǔn)提供要求的尺寸陵叽。
deliveryMode
: 圖像質(zhì)量。有三種值:Opportunistic丛版,在速度與質(zhì)量中均衡巩掺;HighQualityFormat,不管花費多長時間页畦,提供高質(zhì)量圖像胖替;FastFormat,以最快速度提供好的質(zhì)量。
normalizedCropRect
: 用于對原始尺寸的圖像進行裁剪刊殉,基于比例坐標(biāo)殉摔。只在 resizeMode 為 Exact 時有效。
resizeMode 默認(rèn)是 None记焊,這也造成了返回圖像尺寸與要求尺寸不符逸月。這點需要注意。要返回一個指定尺寸的圖像需要避免兩層陷阱:一定要指定 options 參數(shù)遍膜,resizeMode 不能為 None碗硬。
是否裁剪圖片由 targetSize、contentMode來控制瓢颅,裁剪的尺寸由targetSize恩尾、contentMode、resizeMode指定挽懦。
比如
// 下載原圖:
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.progressHandler = (PHAssetImageProgressHandler)progress;
targetSize = PHImageManagerMaximumSize;
contentMode = PHImageContentModeDefault;
// 全屏圖
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.progressHandler = (PHAssetImageProgressHandler)progress;
targetSize = UIScreen.mainScreen.bounds.size;
contentMode = PHImageContentModeAspectFit;
4.2.2 resultHandler可能被多次調(diào)用
見上圖翰意,
- 如果
synchronous
屬性為YES,同步請求信柿,resultHandler只會執(zhí)行一次冀偶,并且返回高質(zhì)量的圖片。
- 但是如果
synchronous
為NO渔嚷,resultHandler是否會被多次調(diào)用取決于deliveryMode
屬性:- 如果
deliveryMode
是.HighQualityFormat 进鸠,resultHandler調(diào)用一次,框架只返回高質(zhì)量圖形病。 - 如果
deliveryMode
是FastFormat客年,resultHandler也只被調(diào)用一次,保證速度盡可能保證圖片質(zhì)量漠吻。 -
deliveryMode
是.Opportunistic Photos 可能會先提供低質(zhì)量的圖像以供臨時顯示量瓜,隨后會將指定尺寸的圖像返回。如果指定尺寸的高質(zhì)量的圖像有緩存侥猩,那么直接提供高質(zhì)量的圖像榔至。如圖,第一次同步調(diào)用請求返回一張模糊的圖,第二次再去下載一張高質(zhì)量的圖片:
- 如果
resultHandler中的info 字典提供了關(guān)于當(dāng)前請求狀態(tài)的信息欺劳,比如:
- 圖像是否必須從 iCloud 請求 (如果你初始化時將 networkAccessAllowed 設(shè)置成 false,那么就必須重新請求圖像) —— PHImageResultIsInCloudKey 铅鲤。
- 當(dāng)前遞送的 UIImage 是否是最終結(jié)果的低質(zhì)量格式划提。當(dāng)高質(zhì)量圖像正在下載時,這個可以讓你給用戶先展示一個預(yù)覽圖像 —— PHImageResultIsDegradedKey邢享。
- 請求 ID (可以便捷的取消請求)鹏往,以及請求是否已經(jīng)被取消。 —— PHImageResultRequestIDKey 和 PHImageCancelledKey骇塘。
如果沒有圖像提供給 result handler伊履,字典內(nèi)還會有一個錯誤信息 —— PHImageErrorKey韩容。
比如用-requestImageForAsset:targetSize:contentMode:options:resultHandler:
接口請求圖片
// 入?yún)ⅲ簐ideo對應(yīng)的PHAsset對象
// info字典返回:
"PHImageResultRequestIDKey" : (int)1
"PHImageResultImageTypeKey" : (long)0
"PHImageResultDeliveredImageFormatKey" : (long)5005
"PHImageResultIsDegradedKey" : @"0"
注: 返回的image是video第一幀的截圖
// 入?yún)ⅲ簣D片對應(yīng)的PHAsset對象
// info字典返回:
"PHImageFileOrientationKey" : (long)0
"PHImageResultWantedImageFormatKey" : (long)5005
"PHImageResultRequestIDKey" : (int)2
"PHImageResultDeliveredImageFormatKey" : (long)4031
"PHImageResultIsDegradedKey" : @"1"
4.3 請求視頻
// 視頻請求對象
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
// 最高質(zhì)量的視頻
options.deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;
// 可從iCloud中獲取圖片
options.networkAccessAllowed = YES;
// 如果是iCloud的視頻,可以獲取到下載進度
options.progressHandler = ^(double progress, NSError *error, BOOL *stop) {
[self updateUserVisibleProgress:progress error:error];
// 此回調(diào)block可能不在UI線程中唐瀑,我們需要在UI線程中更新UI
dispatch_async(dispatch_get_main_queue(), ^{
self.progressView.progress = progress;
});
};
// 方法1
[manager requestPlayerItemForVideo:video options:options resultHandler:....]
// 方法2
[manager requestExportSessionForVideo:video options:options ...];
// 方法3
[manager requestAVAssetForVideo:video options:options resultHandler...];
5. 滾動性能:緩存
5.1 PHCachingImageManager
滾動一系列縮略圖時群凶,我們可以在可視區(qū)域前后維護一些數(shù)據(jù)緩存。如圖:
- 生成PHCachingImageManager實例
- 調(diào)用方法startCachingImagesForAssets:targetSize:contentMode:options:哄辣,并指定 目標(biāo)尺寸target size请梢,內(nèi)容模式content mode,選項options參數(shù)
- 需要從asset對象中獲取圖片的時候力穗,調(diào)用
requestImageForAsset:targetSize:contentMode:options:resultHandler
PHCachingImageManager *cim = [[PHCachingImageManager alloc] init];
NSArray *soonToBeVisibleAssets = [cim startCachingImagesForAssets:soonToBeVisibleAssets
targetSize:targetSize
contentMode:PHImageContentModeAspectFill
options:nil];
NSArray *previouslyVisibleAssets = [cim stopCachingImagesForAssets:previouslyVisibleAssets
targetSize:targetSize
contentMode:PHImageContentModeAspectFill
options:nil];
// 從緩存中讀取相片
// Request an image for the asset from the PHCachingImageManager.
[self.imageManager requestImageForAsset:asset
targetSize:AssetGridThumbnailSize
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
// Set the cell's thumbnail image if it's still showing the same asset.
if ([cell.representedAssetIdentifier isEqualToString:asset.localIdentifier]) {
cell.thumbnailImage = result;
}
}];
官方demo中計算緩存區(qū)域的算法比較有意思
- (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect removedHandler:(void (^)(CGRect removedRect))removedHandler addedHandler:(void (^)(CGRect addedRect))addedHandler {
if (CGRectIntersectsRect(newRect, oldRect)) {
CGFloat oldMaxY = CGRectGetMaxY(oldRect);
CGFloat oldMinY = CGRectGetMinY(oldRect);
CGFloat newMaxY = CGRectGetMaxY(newRect);
CGFloat newMinY = CGRectGetMinY(newRect);
if (newMaxY > oldMaxY) {
CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY));
addedHandler(rectToAdd);
}
if (oldMinY > newMinY) {
CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY));
addedHandler(rectToAdd);
}
if (newMaxY < oldMaxY) {
CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY));
removedHandler(rectToRemove);
}
if (oldMinY < newMinY) {
CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY));
removedHandler(rectToRemove);
}
} else {
addedHandler(newRect);
removedHandler(oldRect);
}
}