Photokit 仿微信實現(xiàn)多圖選擇(上)

git地址: https://github.com/wangjinshan/IJSPhotoSDK
集成文檔已經(jīng)在git更新了 支持cocoapods

項目演示

demo.gif
001.PNG
002.PNG
003.PNG
004.PNG
005.PNG
006.PNG
007.PNG
008.PNG
009.PNG

具體的demo 后面會更新到github上

Photokit介紹

這篇主要介紹如何通過 Photokit獲取數(shù)據(jù)

photokit.jpg

1,基類 PHObject

Photos 框架中的根類PHObject只有一個公開接口 localIdentifier,是對象唯一標志符.PHObject實現(xiàn)了-isEqual 和-hash方法.可以直接使用localIdentifier屬性對PHObject及其子類對象進行對比是否同一個對象

2,數(shù)據(jù)類型

PHAsset 账月、PHAssetCollection、PHCollectionList 是Photos框架中的模型類

PHAsset :代表系統(tǒng)的一個圖片,視頻或者Live Photo
PHAssetCollection:是一組有序的資源集合,包括相冊揍鸟、moments胞锰、智能相冊以及共享照片流.比如:系統(tǒng)相冊里的時刻一個分類宋税,用戶創(chuàng)建的相冊或者智能相冊
PHCollectionList : 相冊集合, 比如:時刻里的年或者包含用戶創(chuàng)建的一個或者多個相冊
表示一組PHCollection,而它本身也是一個PHCollection,因此PHCollection作為一個集合羡玛,可以包含其他集合
如下資源結(jié)構(gòu)圖:


jiegou.png
2.1 PHAsset.h
2.1.1 PHAsset

代表系統(tǒng)的一個圖片鞠苟,視頻或者Live Photo
屬性介紹:

[1] mediaType :資源類型,圖片或者音頻或視頻
 PHAssetMediaTypeUnknown = 0,
 PHAssetMediaTypeImage   = 1,
 PHAssetMediaTypeVideo   = 2,
 PHAssetMediaTypeAudio   = 3,
 
 [2] mediaSubtypes
 圖片又包含全景圖(Panorama)鬓照、HDR圖片熔酷、屏幕截圖、livePhoto .live photo 加3Dtouch效果 我們可以使用照片資源的 mediaSubtypes 屬性驗證資源庫中的圖像在捕捉時是否開啟了 HDR豺裆,拍攝時是否使用了相機應(yīng)用的全景模式
 
 PHAssetMediaSubtypeNone      = 0,
 
 // Photo subtypes
 PHAssetMediaSubtypePhotoPanorama
 PHAssetMediaSubtypePhotoHDR
 PHAssetMediaSubtypePhotoScreenshot
 PHAssetMediaSubtypePhotoLive
 PHAssetMediaSubtypePhotoDepthEffect
 
 // Video subtypes
 PHAssetMediaSubtypeVideoStreamed      = (1UL << 16),
 PHAssetMediaSubtypeVideoHighFrameRate = (1UL << 17),
 PHAssetMediaSubtypeVideoTimelapse
 
 [3] pixelWidth 像素寬度 pixelHeight 高度
 
 [4] creationDate 創(chuàng)建時間   modificationDate 修改時間  location 位置信息 duration時長
 
 [5] hidden 要驗證一個資源是否被用戶標記為收被隱藏拒秘,只要檢查 PHAsset 實例的 hidden 屬性即可号显。
 [6] Favorite  布爾值,用戶是否標記資源為"收藏"躺酒,我們平時瀏覽照片或視頻押蚤,在下方點??就表示收藏這張圖
 
 [7] representsBurst 和 burstSelectionTypes: 對于一個資源,如果其 PHAsset 的 representsBurst 屬性為 true羹应,則表示這個資源是一系列連拍照片中的代表照片 (多張照片是在用戶按住快門時拍攝的)揽碘。它還有一個屬性是 burstIdentifier,如果想要獲取連拍照片中的剩余的其他照片园匹,可以通過將這個值傳入 fetchAssetsWithBurstIdentifier(...) 方法來獲取雳刺。用戶可以在連拍的照片中做標記;此外裸违,系統(tǒng)也會自動用各種試探來標記用戶可能會選擇的潛在代表照片掖桦。這個元數(shù)據(jù)是可以通過 PHAsset 的 burstSelectionTypes 屬性來訪問。這個屬性是用三個常量組成的位掩碼:.UserPick 表示用戶手動標記的資源供汛,.AutoPick 表示用戶可能標記的潛在資源枪汪,.None 表示沒有標記的資源
 
 [8] localIdentifier Photos 框架中的根類PHObject只有一個公開接口localIdentifier,是對象唯一唯一標志符.PHObject實現(xiàn)了-isEqual 和-hash方法.可以直接使用localIdentifier屬性對PHObject及其子類對象進行對比是否同一個對象
 
 方法
 // 可執(zhí)行編輯操作
 - (BOOL)canPerformEditOperation:(PHAssetEditOperation)editOperation;
常見的獲取資源的方法
// 獲取所有的資源  options是獲取資源的條件下文介紹
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithOptions:(nullable PHFetchOptions *)options;  
// 從相冊中獲取資源 , assetCollection 可以傳入相冊的對象
 + (PHFetchResult<PHAsset *> *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(nullable PHFetchOptions *)options; 
2.2 PHCollection.h
2.2.1, PHCollection :一個抽象類,是PHAssetCollection和PHColletionList的父類

屬性:

[1.1]  localizedTitle 相冊的標題
// 獲取資源的方法
+ (PHFetchResult<PHCollection *> *)fetchCollectionsInCollectionList:(PHCollectionList *)collectionList options:(nullable PHFetchOptions *)options;
2.2.2 , PHAssetCollection 相冊(PHAsset集合)

PHAssetCollection是一組有序的資源集合,包括相冊怔昨、moments雀久、智能相冊以及共享照片流.比如:系統(tǒng)相冊里的時刻一個分類,用戶創(chuàng)建的相冊或者智能相冊
屬性:

[2.1] assetCollectionType  指定資源集合類型來源趁舀,比如相冊或者“時刻”相冊
 PHAssetCollectionTypeAlbum      = 1,      // 用戶相冊
 PHAssetCollectionTypeSmartAlbum = 2,  // 智能相冊
 PHAssetCollectionTypeMoment     = 3,     // 時刻”相冊
 
 [2.2] assetCollectionSubtype 子類型
 enum PHAssetCollectionType : Int {
 case Album             //從 iTunes 同步來的相冊赖捌,以及用戶在 Photos 中自己建立的相冊
 case SmartAlbum    //經(jīng)由相機得來的相冊
 case Moment            //Photos 為我們自動生成的時間分組的相冊
 }
 
 enum PHAssetCollectionSubtype : Int
 {
 PHAssetCollectionSubtypeSmartAlbumSlomoVideos
 PHAssetCollectionSubtypeSmartAlbumSelfPortraits
 PHAssetCollectionSubtypeSmartAlbumScreenshots
 PHAssetCollectionSubtypeSmartAlbumDepthEffect
 PHAssetCollectionSubtypeSmartAlbumLivePhotos
 // Used for fetching, if you don't care about the exact subtype
 PHAssetCollectionSubtypeAny = NSIntegerMax
 
 case PHAssetCollectionSubtypeAlbumRegular              //用戶在 Photos 中創(chuàng)建的相冊
 case PHAssetCollectionSubtypeAlbumSyncedEvent      //使用 iTunes 從 Photos 照片庫或者 iPhoto 照片庫同步過來的事件。然而赫编,在iTunes 12 以及iOS 9.0 beta4上巡蘸,選用該類型沒法獲取同步的事件相冊,而必須使用AlbumSyncedAlbum擂送。
 case PHAssetCollectionSubtypeAlbumSyncedFaces      //使用 iTunes 從 Photos 照片庫或者 iPhoto 照片庫同步的人物相冊悦荒。
 case PHAssetCollectionSubtypeAlbumSyncedAlbum          //從iPhoto同步到設(shè)備的相冊
 case PHAssetCollectionSubtypeAlbumImported                 //從相機或是外部存儲導(dǎo)入的相冊,完全沒有這方面的使用經(jīng)驗嘹吨,沒法驗證搬味。
 
 case PHAssetCollectionSubtypeAlbumMyPhotoStream    //用戶的 iCloud 照片流
 case PHAssetCollectionSubtypeAlbumCloudShared          //用戶使用 iCloud 共享的相冊
 case PHAssetCollectionSubtypeSmartAlbumGeneric        //文檔解釋為非特殊類型的相冊,主要包括從 iPhoto 同步過來的相冊蟀拷。
 case PHAssetCollectionSubtypeSmartAlbumPanoramas   //相機拍攝的全景照片
 case PHAssetCollectionSubtypeSmartAlbumVideos          //相機拍攝的視頻
 case PHAssetCollectionSubtypeSmartAlbumFavorites       //收藏文件夾
 case PHAssetCollectionSubtypeSmartAlbumTimelapses      //延時視頻文件夾碰纬,同時也會出現(xiàn)在視頻文件夾中
 case PHAssetCollectionSubtypeSmartAlbumAllHidden       //包含隱藏照片或視頻的文件夾
 case PHAssetCollectionSubtypeSmartAlbumRecentlyAdded //相機近期拍攝的照片或視頻
 case PHAssetCollectionSubtypeSmartAlbumBursts                  //連拍模式拍攝的照片
 case PHAssetCollectionSubtypeSmartAlbumUserLibrary  //這個命名最神奇了,就是相機相冊问芬,所有相機拍攝的照片或視頻都會出現(xiàn)在該相冊中悦析,而且使用其他應(yīng)用保存的照片也會出現(xiàn)在這里,用戶創(chuàng)建出來的
 case Any //包含所有類型
 }
 
 [2.3] startDate endDate 開始 結(jié)束時間
 
 [2.4] estimatedAssetCount :估算的asset數(shù)量,不精確
 
 [2.5] CLLocation *approximateLocation;  大概的位置
 [2.6] NSArray<NSString *> *localizedLocationNames; 位置地區(qū)的名字數(shù)組

2.2.3 , PHCollectionList : 相冊集合

表示一組PHCollection,而它本身也是一個PHCollection,因此PHCollection作為一個集合此衅,可以包含其他集合
屬性:

 [3.1] collectionListType
 [3.2] collectionListSubtype
 [3.3] startDate
 [3.4 ] endDate

獲取模型數(shù)據(jù)
PHAsset 强戴、PHCollection亭螟、PHCollectionList有一系列類方法可供我們訪問資源的元數(shù)據(jù)

 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)的默認值最域,當(dāng)我們調(diào)用如上所示方法獲取時谴分,可以直接傳nil
 

3, 搜索的條件

3.1 PHFetchOptions.h

PHFetchOptions : option的集合,對asset對象進行 過濾羡宙,排序和管理
屬性:

 [1] predicate 做選擇的約束條件狸剃。比如,只獲取圖片狗热,不獲取視頻。指定 PHAssetMediaType為image.
 
 [2]  sortDescriptors 可指定字段用來對獲取結(jié)果進行排序
 
 [3] includeHiddenAssets 獲取結(jié)果是否包括被隱藏的資源
 
 [4] includeAllBurstAssets 獲取結(jié)果是否包括連拍資源
 
 [5] includeAssetSourceTypes 資源的來源
 PHAssetSourceTypeNone
 PHAssetSourceTypeUserLibrary
 PHAssetSourceTypeCloudShared
 PHAssetSourceTypeiTunesSynced
 
 [6] fetchLimit  搜索結(jié)果的限制 ,0 表示無限制
 
 [7] wantsIncrementalChangeDetails ,搜索結(jié)果細節(jié)變化

4, 搜索的結(jié)果 PHFetchResult

PHFetchResult.h
PHFetchResult: 類似數(shù)組,包含assets或者collections有序的一系列集合

特點: 同步快速獲取結(jié)果,
即使結(jié)果集很大虑省,框架也能保證獲取速度. 因為它不會一次性將所有結(jié)果放進內(nèi)存匿刮,而是按需批量加載
可以用類似 NSArray 的接口來訪問PHFetchResult結(jié)果內(nèi)的集合
提供快速枚舉的方法

  • (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(ObjectType obj, NSUInteger idx, BOOL *stop))block;
    就算滿足請求的照片庫內(nèi)容發(fā)生了改變,獲取方法所返回的 PHFetchResult 對象是不會自動更新探颈。在后面的小節(jié)中熟丸,我們會介紹如何對返回的 PHFetchResult 對象的改變進行觀察并處理更新內(nèi)容。
    可以借助 PHObjectChangeDetails 或 PHFetchResultChangeDetails 對象來觀察這些變化

綜合例子如下:

// 獲取相機膠卷的相冊得到PHAsset對象放到IJSAlbumModel中
-(void)getCameraRollAlbumContentImage:(BOOL)contentImage contentVideo:(BOOL)contentVideo  completion:(void (^)(IJSAlbumModel *model))completion
{
    __block IJSAlbumModel *model;
    if (iOS8Later)
    {
        PHFetchOptions *option = [[PHFetchOptions alloc] init];
        if (!contentVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
        if (!contentImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
                                                    PHAssetMediaTypeVideo];
        if (!self.sortAscendingByModificationDate)
        {
            option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
        }
        PHFetchResult<PHAssetCollection *>  *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
        
        for (PHAssetCollection *collection in smartAlbums)
        {
            if (![collection isKindOfClass:[PHAssetCollection class]]) continue; // 有可能是PHCollectionList類的的對象伪节,過濾掉
            if ([self isCameraRollAlbum:collection.localizedTitle])
            {
                PHFetchResult<PHAsset *>  *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
                model = [self modelWithResult:fetchResult name:collection.localizedTitle];
                if (completion) completion(model);
                break;
            }
        }
    }
    else
    {
        [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            if ([group numberOfAssets] < 1) return;
            NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
            if ([self isCameraRollAlbum:name])
            {
                model = [self modelWithResult:group name:name];
                if (completion) completion(model);
                *stop = YES;
            }
        } failureBlock:nil];
    }
}

至此我們已經(jīng)成功的獲取了 asset 對象



接下來我們將我們獲取的 PHAsset對象解析成我們需要 UIImage 對象
需要的類介紹:

5, 解析PHAsset

PHImageManager.h

5.1 PHImageManager

在框架中是個單例對象光羞,用[PHImageManager defaultManager]獲取,它提供了加載圖片和視頻的方法,解析 PHAsset 資源
方法介紹:

// 獲取自定義大小的圖片
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;
官方注釋翻譯:
 如果獲取的資源的寬高比不符合, contentMode 決定現(xiàn)實的大小
 PHImageContentModeAspectFit:  等比例適應(yīng)
 PHImageContentModeAspectFill:  等比例縮放適應(yīng)
 PHImageContentModeDefault = PHImageContentModeAspectFit  默認值
 [PHImageRequestOptions isSynchronous] returns NO (or options is nil), resultHandler 可能會請求多次
 deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic
 默認情況下,這些API是異步執(zhí)行怀大,但是我們可以通過options參數(shù)中的synchronous屬性纱兑,設(shè)置為同步執(zhí)行,這些方法會阻塞當(dāng)前調(diào)用線程直到下載完成或者發(fā)生錯誤
 請求取消將不再返回 resultHandler

方法參數(shù)解讀:
 asset:   需要解析的資源
 targetSize: 需要獲取的圖像的尺寸化借,如果輸入的尺寸大于資源原圖的尺寸潜慎,則只返回原圖。需要注意在 PHImageManager 中蓖康,所有的尺寸都是用 Pixel 作為單位(Note that all sizes are in pixels)铐炫,因此這里想要獲得正確大小的圖像,需要把輸入的尺寸轉(zhuǎn)換為 Pixel蒜焊。如果需要返回原圖尺寸倒信,可以傳入 PhotoKit 中預(yù)先定義好的常量?PHImageManagerMaximumSize,表示返回可選范圍內(nèi)的最大的尺寸泳梆,即原圖尺寸
 contentMode: 圖像的剪裁方式,控制照片應(yīng)該以按比例縮放還是按比例填充的方式放到最終展示的容器內(nèi)鳖悠。注意如果 targetSize 傳入PHImageManagerMaximumSize榜掌,則 contentMode 無論傳入什么值都會被視為 PHImageContentModeDefault
 options: PHImageRequestOptions 的實例,可以控制的內(nèi)容相當(dāng)豐富竞穷,包括圖像的質(zhì)量唐责、版本,也會有參數(shù)控制圖像的剪裁
 resultHandler: 請求結(jié)束后被調(diào)用的 block瘾带,返回一個包含資源對于圖像的 UIImage 和包含圖像信息的一個 NSDictionary鼠哥,在整個請求的周期中,這個 block 可能會被多次調(diào)用

// 獲取原圖數(shù)據(jù)
請求大圖 ,回調(diào)只執(zhí)行一次,deliveryMode直接被忽略,設(shè)置了PHImageRequestOptionsVersionCurrent 并且資源被調(diào)整過,則返回最大的圖
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(nullable PHImageRequestOptions *)options resultHandler:(void(^)(NSData *__nullable imageData, NSString *__nullable dataUTI, UIImageOrientation orientation, NSDictionary *__nullable info))resultHandler;
// 取消正在加載的數(shù)據(jù)線
- (void)cancelImageRequest:(PHImageRequestID)requestID;
5.2 獲取圖片資源的控制條件類 PHImageRequestOptions

PHImageRequestOptions中包含了一系列控制請求圖像的屬性
如果resizeMode所控制的剪裁結(jié)果有所沖突看政,PhotoKit 會以 resizeMode 的結(jié)果為準
屬性詳解:

1,  PHImageRequestOptionsVersion version:

 這個屬性是指獲取的圖像是否需要包含系統(tǒng)相冊“編輯”功能處理過的信息(如濾鏡朴恳,旋轉(zhuǎn)等)
 圖片編輯extension,可以根據(jù)次枚舉獲取原圖或者是經(jīng)編輯過的圖片
 PHImageRequestOptionsVersionCurrent = 0, //當(dāng)前的(編輯過?經(jīng)過編輯的圖:原圖)
 PHImageRequestOptionsVersionUnadjusted, //經(jīng)過編輯的圖
 PHImageRequestOptionsVersionOriginal       //原始圖片
 
  2, PHImageRequestOptionsDeliveryMode deliveryMode:
 則用于控制請求的圖片質(zhì)量
 PHImageRequestOptionsDeliveryModeOpportunistic:在速度與質(zhì)量中均衡 根據(jù)我options.synchronous判斷返回結(jié)果是一個或多個
 PHImageRequestOptionsDeliveryModeHighQualityFormat 制定的同步返回一個結(jié)果允蚣,返回的圖片質(zhì)量是比我們設(shè)定的size會好一點(實際上與PHImageRequestOptions的resizeMode枚舉相關(guān)) 高質(zhì)量圖
 PHImageRequestOptionsDeliveryModeFastFormat 僅返回一次于颖,效率較高之余獲得的圖質(zhì)量不太好,速度最快
 
 
  3, PHImageRequestOptionsResizeMode resizeMode:  PHImageRequestOptionsResizeModeNone (or no resize)無效 屬性控制圖像的剪裁
  
 4 CGRect normalizedCropRect: 用于對原始尺寸的圖像進行裁剪,基于比例坐標嚷兔。只在 resizeMode 為 Exact 時有效
 5 BOOL networkAccessAllowed; 是否允許從 icloud請求資源 另一個和 iCloud 相關(guān)的屬性是 progressHandler森渐。你可以將它設(shè)為一個PHAssetImageProgressHandler 的 block,當(dāng)從 iCloud 下載照片時冒晰,它就會被圖像管理器自動調(diào)用
 6 BOOL synchronous 是否為同步操作同衣,默認為NO,如果設(shè)置為YES則壶运,相關(guān)模式下只會返回一張圖片
  PHAssetImageProgressHandler progressHandler 當(dāng)圖像需要從 iCloud 下載時耐齐,這個 block 會被自動調(diào)用,block 中會返回圖像下載的進度蒋情,圖像的信息埠况,出錯信息。開發(fā)者可以利用這些信息反饋給用戶當(dāng)前圖像的下載進度以及狀況棵癣,但需要注意?progressHandler 不在主線程上執(zhí)行辕翰,因此在其中需要操作 UI,則需要手工放到主線程執(zhí)行
 上面有提到浙巫,requestImageForAsset 中的參數(shù)?resultHandler 可能會被多次調(diào)用金蜀,這種情況就是圖像需要從 iCloud 中下載的情況。在?requestImageForAsset 返回的內(nèi)容中的畴,一開始的那一次請求中會返回一個小尺寸的圖像版本渊抄,當(dāng)高清圖像還在下載時,開發(fā)者可以首先給用戶展示這個低清的圖像版本丧裁,然后 block 在多次調(diào)用后护桦,最終會返回高清的原圖。至于當(dāng)前返回的圖像是哪個版本的圖像煎娇,可以通過 block 返回的 NSDictionary info 中獲知二庵,PHImageResultIsDegradedKey 表示當(dāng)前返回的 UIImage 是低清圖贪染。如果需要判斷是否已經(jīng)獲得高清圖,可以這樣判斷:
 
 BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
 
 requestImageForAsset 發(fā)出對圖像的請求時催享,如果在同一個 PHImageManager 中同時對同一個資源發(fā)出圖像請求杭隙,請求的進度是可以共享的,因此我們可以利用這個特性因妙,把 PHImageManager 以單例的形式使用痰憎,這樣在切換界面時也不用擔(dān)心無法傳遞圖像的下載進度。例如攀涵,在圖像的列表頁面觸發(fā)了下載圖像铣耘,當(dāng)我們離開列表頁面進入預(yù)覽大圖界面時,并不用擔(dān)心會重新圖像會重新下載以故,只要沒有手工取消圖像下載蜗细,進入預(yù)覽大圖界面下載圖像會自動繼續(xù)從上次的進度下載圖像
5.3 livePhoto篩選類 PHLivePhotoRequestOptions
 PHImageRequestOptionsVersion version;
  PHImageRequestOptionsDeliveryMode deliveryMode;
  BOOL networkAccessAllowed;
  PHAssetImageProgressHandler progressHandler;// 網(wǎng)絡(luò)加載的進度
5.4 video篩選類 PHVideoRequestOptions
BOOL networkAccessAllowed;
PHVideoRequestOptionsVersion version;
 PHVideoRequestOptionsDeliveryMode deliveryMode;
 PHAssetVideoProgressHandler progressHandler;  // 網(wǎng)絡(luò)進度
 
 // 獲取視頻
 - (PHImageRequestID)requestPlayerItemForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVPlayerItem *__nullable playerItem, NSDictionary *__nullable info))resultHandler;
 // 導(dǎo)出視頻方法
 - (PHImageRequestID)requestAVAssetForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVAsset *__nullable asset, AVAudioMix *__nullable audioMix, NSDictionary *__nullable info))resultHandler;
 
5.5 PHPhotoLibrary

PHPhotoLibrary:
系統(tǒng)中PHPhotoLibrary單例對象 是用來維護用戶照片庫。當(dāng)我們需要編輯資源對象元數(shù)據(jù)怒详、資源內(nèi)容炉媒、或者插入新的資源對象等,都可以借助通過PHPhotoLibrary單例對象執(zhí)行block昆烁,block中創(chuàng)建我們指定的請求對象(比如PHAssetChangeRequest,PHAssetCollectionChangeRequest, PHCollectionListChangeRequest的對象)橱野。photoLibraryDidChange(changeInfo: PHChange!)中進行
授權(quán)狀態(tài)

 {
 PHAuthorizationStatusNotDetermined = 0, // 未選擇
 PHAuthorizationStatusRestricted,        // 用戶受到某些限制,不能自己決定善玫,比如:家長控制
 PHAuthorizationStatusDenied,            // 用戶明確拒絕
 PHAuthorizationStatusAuthorized         // 已經(jīng)授權(quán)
 }
 // 協(xié)議 :
 PHPhotoLibraryChangeObserver:
 PHPhotoLibraryChangeObserver 協(xié)議能讓我們知道照片相冊庫中的改變。Photos會發(fā)送系統(tǒng)圖片改變的消息密强,我們可以遵守PHPhotoLibraryChangeObserver協(xié)議茅郎,并通過 PHPhotoLibrary的registerChangeObserver方法將對象注冊為觀察者,時時接收照片改變的消息或渤。
 // 串行隊列 相冊數(shù)據(jù)改變 知道照片相冊庫中的改變
 - (void)photoLibraryDidChange:(PHChange *)changeInstance;
 
 // 單利初始化
 + (PHPhotoLibrary *)sharedPhotoLibrary;
 //判斷授權(quán)
 + (PHAuthorizationStatus)authorizationStatus;
 請求授權(quán)
 + (void)requestAuthorization:(void(^)(PHAuthorizationStatus status))handler;

 //  執(zhí)行同步和異步數(shù)據(jù)
 - (void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler;
 - (BOOL)performChangesAndWait:(dispatch_block_t)changeBlock error:(NSError *__autoreleasing *)error;
 
 // 將對象注冊為觀察者系冗,時時接收照片改變的消息。
 - (void)registerChangeObserver:(id<PHPhotoLibraryChangeObserver>)observer;
 - (void)unregisterChangeObserver:(id<PHPhotoLibraryChangeObserver>)observer;

綜合例子

- (PHImageRequestID)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed
{
    if ([asset isKindOfClass:[PHAsset class]]) {
        CGSize imageSize;
        if (photoWidth < JSScreenWidth && photoWidth < _photoPreviewMaxWidth) {
            imageSize = assetGridThumbnailSize;
        } else {
            PHAsset *phAsset = (PHAsset *)asset;
            CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight;
            CGFloat pixelWidth = photoWidth * JSScreenScale * 1.5;
            // 超寬圖片
            if (aspectRatio > 1) {
                pixelWidth = pixelWidth * aspectRatio;
            }
            // 超高圖片
            if (aspectRatio < 0.2) {
                pixelWidth = pixelWidth * 0.5;
            }
            CGFloat pixelHeight = pixelWidth / aspectRatio;
            imageSize = CGSizeMake(pixelWidth, pixelHeight);
        }
        
        __block UIImage *image;
        PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
        option.resizeMode = PHImageRequestOptionsResizeModeFast;
        int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
            if (result) {
                image = result;
            }
            BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
            if (downloadFinined && result) {
                result = [self fixOrientation:result];
                if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
            }
            // Download image from iCloud / 從iCloud下載圖片
            if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) {
                PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
                options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (progressHandler) {
                            progressHandler(progress, error, stop, info);
                        }
                    });
                };
                options.networkAccessAllowed = YES;
                options.resizeMode = PHImageRequestOptionsResizeModeFast;
                [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                    UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
                    resultImage = [self scaleImage:resultImage toSize:imageSize];
                    if (!resultImage) {
                        resultImage = image;
                    }
                    resultImage = [self fixOrientation:resultImage];
                    if (completion) completion(resultImage,info,NO);
                }];
            }
        }];
        return imageRequestID;
    } else if ([asset isKindOfClass:[ALAsset class]]) {
        ALAsset *alAsset = (ALAsset *)asset;
        dispatch_async(dispatch_get_global_queue(0,0), ^{
            CGImageRef thumbnailImageRef = alAsset.thumbnail;
            UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef scale:2.0 orientation:UIImageOrientationUp];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) completion(thumbnailImage,nil,YES);
                
                if (photoWidth == JSScreenWidth || photoWidth == _photoPreviewMaxWidth) {
                    dispatch_async(dispatch_get_global_queue(0,0), ^{
                        ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
                        CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
                        UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
                        
                        dispatch_async(dispatch_get_main_queue(), ^{
                            if (completion) completion(fullScrennImage,nil,NO);
                        });
                    });
                }
            });
        });
    }
    return 0;
}

至此關(guān)于photo獲取資源的方法全部結(jié)束


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末薪鹦,一起剝皮案震驚了整個濱河市掌敬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌池磁,老刑警劉巖奔害,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異地熄,居然都是意外死亡华临,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門端考,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雅潭,“玉大人揭厚,你說我怎么就攤上這事》龉” “怎么了筛圆?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長椿浓。 經(jīng)常有香客問我太援,道長,這世上最難降的妖魔是什么轰绵? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任粉寞,我火速辦了婚禮,結(jié)果婚禮上左腔,老公的妹妹穿的比我還像新娘唧垦。我一直安慰自己,他們只是感情好液样,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布振亮。 她就那樣靜靜地躺著,像睡著了一般鞭莽。 火紅的嫁衣襯著肌膚如雪坊秸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天澎怒,我揣著相機與錄音褒搔,去河邊找鬼。 笑死喷面,一個胖子當(dāng)著我的面吹牛星瘾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惧辈,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼琳状,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盒齿?” 一聲冷哼從身側(cè)響起念逞,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎边翁,沒想到半個月后翎承,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡倒彰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年审洞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡芒澜,死狀恐怖仰剿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情痴晦,我是刑警寧澤南吮,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站誊酌,受9級特大地震影響部凑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碧浊,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一涂邀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧箱锐,春花似錦比勉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至臊恋,卻和暖如春衣洁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抖仅。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工坊夫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撤卢。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓践樱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凸丸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

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

  • 相冊適配 前言 由于在iOS8及以后蘋果將原有的操作相冊的ALAssetsLibrary framework替換為...
    wentianen閱讀 1,816評論 0 6
  • 本文轉(zhuǎn)載自Kayo Lee發(fā)表的文章腻惠,本文鏈接:http://kayosite.com/ios-developme...
    JackyHeWei閱讀 10,452評論 10 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)欲虚,斷路器集灌,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • demo下載地址在最下方 一、AssetsLibrary iOS提供的AssetsLibrary是用來讀取和操作本...
    Archer_bling閱讀 6,008評論 19 23
  • 沒有等到月光和花開 也沒有等到晨風(fēng)和離別的問候 在我眼中 相遇可以無數(shù)遍 可我愛你,只有一遍 可你不愛我欣喧,也只有一...
    子禾CC閱讀 125評論 0 0