PhotoKit制作相冊或選擇器(一):初識Photos

前言

不知讀者們在平日里使用聊天工具時,有沒有發(fā)表情的習慣。是不是常常在與朋友們聊天時,一言不合就掀起一場斗圖大會呢。小編作為一個喜歡搞事情的小碼農(nóng),上班唯一能放松的事情就是和同事在群里吹牛逼斗斗圖了(不搞點事情代碼怎么吐的動呢)。
找不到圖源,微信表情又有上限等,種種問題讓我施展不出真正的斗圖實力(中毒太深)。非得搞點事情的我計劃開發(fā)一款制作管理GIF表情的相冊,名字叫斗逗圖(目前五菱宏光版正在審核中......)
這波廣告小編打得自己都臉紅了。。。那來切入正題吧,在開發(fā)過程中,我需要通過圖片選擇器選擇多張圖片,可是強大的UIImagePickerController卻沒有多選功能,這讓我很憂桑,看了看Github,已經(jīng)有比較好的輪子,但樣式固定死了,太花哨了,畢竟咱是五菱宏光,漂移之王,花哨的輪子漂不起來,還是自己用Photos造一個吧。

關于Photos

資源

PHObject:資源基類,PHAssetPHCollecton等都繼承它,它包含了一個屬性localIdentifier,它是唯一的,所以我們可以通過此屬性來判斷資源對象是否是同一個
PHAsset:代表一個在相冊中的圖片或視頻,它本身并不儲存圖片或視頻資源,它存放的是metaData,需要通過PHImageManager來請求才能獲取圖片或視頻資源。
PHCollection:照片庫中單獨輕量不可變的集合對象
PHAssetCollectionPHCollection的子類,可以通過它獲取系統(tǒng)自帶的相冊信息
PHCollectionList:既是PHCollection的子類,也是PHCollection的集合
PHFetchResult:很像NSFetchRequest吧,它也有predicatesortDescriptors;使用起來,它類似NSArray,可以通過遍歷獲取儲存的各個元素;還能通過觀察者模式來檢測相冊內(nèi)容是否變化。

獲取資源

PHAssetCollection類方法獲取相冊的資源

#pragma mark - Fetching asset collections

+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options;

// Smart Albums are not supported, only Albums and Moments
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsContainingAsset:(PHAsset *)asset withType:(PHAssetCollectionType)type options:(nullable PHFetchOptions *)options;

// assetGroupURLs are URLs retrieved from ALAssetGroup's ALAssetsGroupPropertyURL
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithALAssetGroupURLs:(NSArray<NSURL *> *)assetGroupURLs options:(nullable PHFetchOptions *)options;

#pragma mark - Fetching moment asset collections

+ (PHFetchResult<PHAssetCollection *> *)fetchMomentsInMomentList:(PHCollectionList *)momentList options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAssetCollection *> *)fetchMomentsWithOptions:(nullable PHFetchOptions *)options;

PHAsset類方法獲取分類過后的資源

#pragma mark - Fetching assets

+ (PHFetchResult<PHAsset *> *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;
+ (nullable PHFetchResult<PHAsset *> *)fetchKeyAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithBurstIdentifier:(NSString *)burstIdentifier options:(nullable PHFetchOptions *)options;

// Fetches PHAssetSourceTypeUserLibrary assets by default (use includeAssetSourceTypes option to override)
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithOptions:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithMediaType:(PHAssetMediaType)mediaType options:(nullable PHFetchOptions *)options;

// assetURLs are URLs retrieved from ALAsset's ALAssetPropertyAssetURL
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithALAssetURLs:(NSArray<NSURL *> *)assetURLs options:(nullable PHFetchOptions *)options;

返回的類型都是PHFetchResult,里面存放的并不是一個個的圖片原始資源,而只是一個個包含元數(shù)據(jù)的PHAsset。那我們該如何獲取圖片的原始資源呢?這就該用到PHImageManager類。

請求資源

PHImageManager
此類提供了請求加載圖片或視頻數(shù)據(jù)的方法,既可以獲取原始大小的圖片,也能獲取縮略圖,同時也可以取回用作播放的AVFoundation相關對象或者操作視頻資源。
當同時加載多個資源很快顯示出來時, 可以使用PHCachingImageManager
類預加載圖片至緩存,這個會在之后的文章中寫到。

以下方法都是實例方法,調用時需要使用defaultManager

請求圖片

方法列表:
#pragma mark - Image
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;


// resultHandler for asynchronous requests, always called on main thread
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(nullable PHImageRequestOptions *)options resultHandler:(void(^)(NSData *__nullable imageData, NSString *__nullable dataUTI, UIImageOrientation orientation, NSDictionary *__nullable info))resultHandler;
//請求方法都返回了PHImageRequestID,可以通過此ID來取消請求
- (void)cancelImageRequest:(PHImageRequestID)requestID;
targetSize

目標尺寸

contentMode

如果資源的比例與所給的目標大小不匹配的話,contentMode決定了圖片如何改變
(詳細可看PHImageRequestOptionsDeliveryModePHImageRequestOptionsResizeMode)

  •  **PHImageContentModeAspectFit**:使圖片根據(jù)目標大小完整顯示 
    
  •  **PHImageContentModeAspectFill**:使圖片根據(jù)目標大小裁剪顯示
    
  •  **PHImageContentModeDefault**: 當尺寸設置為```PHImageManagerMaximumSize```時使用```PHImageContentModeDefault```,得到的結果沒有經(jīng)過縮放和裁剪
    
options
  • version
    version等于PHImageRequestOptionsVersionCurrent請求返回資源是已經(jīng)調整過后最大的圖片數(shù)據(jù)
  • synchronous
    請求是否同步執(zhí)行,值為NO時,會根據(jù)deliveryMode這個屬性,等待方法的回調;當為YES時,deliveryMode的值會被忽略,resultHandler這個回調也只會執(zhí)行一次
  • resizeMode:圖像變化方式。
Fast:盡快地提供接近要求的尺寸;
Exact:精準提供要求的尺寸。
deliveryMode:圖像質量。
Opportunistic:臨時圖像;
HighQualityFormat:高質量圖像;
FastFormat,以最快速度提供好的質量。 這個屬性只有在 synchronous 為 true 時有效。
  • normalizedCropRect
    用于對原始尺寸的圖像進行裁剪,基于比例坐標。只在 resizeModeExact 時有效。
resultHandler

此代碼塊是異步執(zhí)行的,如果deliveryMode等于PHImageRequestOptionsDeliveryModeOpportunistic時,先會同步返回一個臨時的低質量資源,之后當請求到所需的圖片資源時,會異步返回;options 參數(shù)的作用就是來定制這些行為

請求LivePhoto

請求LivePhoto資源。如果 PHLivePhotoRequestOptions
deliveryMode
PHImageRequestOptionsDeliveryModeOpportunistic或者optionsnil時,resultHandler回調不止一次,并且有可能會在同步方法返回前先返回
resultHandler回調代碼塊的Info字典PHImageResultIsDegradedKey對應的值代表是否低質量的LivePhoto已經(jīng)提供

#pragma mark - Live Photo
//Live Photo
- (PHImageRequestID)requestLivePhotoForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHLivePhotoRequestOptions *)options resultHandler:(void (^)(PHLivePhoto *__nullable livePhoto, NSDictionary *__nullable info))resultHandler NS_AVAILABLE_IOS(9_1);

請求視頻

#pragma mark - Video

//可播放視頻音頻資源
- (PHImageRequestID)requestPlayerItemForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVPlayerItem *__nullable playerItem, NSDictionary *__nullable info))resultHandler;

// 導出會話
- (PHImageRequestID)requestExportSessionForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options exportPreset:(NSString *)exportPreset resultHandler:(void (^)(AVAssetExportSession *__nullable exportSession, NSDictionary *__nullable info))resultHandler;

// 其他
- (PHImageRequestID)requestAVAssetForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVAsset *__nullable asset, AVAudioMix *__nullable audioMix, NSDictionary *__nullable info))resultHandler;

觀察相冊變更

相冊里多了一張照片,如何及時的顯示出來呢?
此時PHPhotoLibraryChangeObserver的作用就體現(xiàn)出來了
顧名思義,它就類似一個觀察者,監(jiān)測變化,反應變化。
使用步驟:

  1. 添加此協(xié)議<PHPhotoLibraryChangeObserver>
- (void)viewWillAppear:(BOOL)animated {
    //注冊觀察相冊變化的觀察者
    [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
}
- (void)dealloc {
    //銷毀觀察相冊變化的觀察者
    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}

2.實現(xiàn)協(xié)議

- (void)photoLibraryDidChange:(PHChange *)changeInstance;

PHChangechangeDetailsForFetchResult:方法檢測照片集合內(nèi)是否產(chǎn)生變化,入?yún)楸粰z測的照片集合

- (nullable PHFetchResultChangeDetails *)changeDetailsForFetchResult:(PHFetchResult *)object;

結束語

以上是關于Photos框架的簡單介紹,一些基本的用法,足夠開發(fā)一款簡單的相冊或者選擇器啦!
這回買好零件,下一篇就開始造我們五菱宏光專屬輪子了。
敬請期待~

小編對文檔的理解可能會有些出入,有錯誤希望讀者能積極指出,我會及時更正。
如果喜歡,請持續(xù)關注,順便點個喜歡噢??????

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容