Photos
Photos 框架是iOS 8之后用于替代AssetsLibrary的一個現(xiàn)代化框架揽惹,幾年以來,相機應(yīng)用與照片應(yīng)用發(fā)生了顯著的變化四康,增加了許多新特性搪搏,Photos可以獲取相冊中的所有圖片和視頻資源,包括iCloud Photo library 和 Live Photos闪金,并且能夠異步獲取并緩存縮略圖和原圖疯溺。
獲取資源
相冊中有兩種資源可供獲取,分別是PHAsset
和 PHCollection
哎垦,PHAsset
代表一個相冊中的文件,這個文件可以是視頻囱嫩、音頻或圖片,我們可以通過PHAsset
來獲取這個文件的所有信息撼泛,包括定位挠说、創(chuàng)建時間、名稱等等愿题。而PHCollection
則是一個集合损俭,PHCollection
有兩個子類分別是PHAssetCollection
和PHCollectionList
,其中PHAssetCollection
代表一個相冊潘酗,也就是PHAsset的集合杆兵,如自拍相冊、截屏相冊仔夺、智能相冊等琐脏。PHCollectionList
代表一個自身的集合,也就是PHCollection
的集合缸兔,通常用來獲取相冊列表
獲取請求
所有的獲取操作都是由PHAsset和PHCollection的類方法實現(xiàn)的日裙,方法如下:
//獲取一個相冊中的所有文件
open class func fetchAssets(in assetCollection: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult<PHAsset>
//通過PHAsset的LocalIdentifier獲取PHAsset
open class func fetchAssets(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHAsset> // includes hidden assets by default
open class func fetchKeyAssets(in assetCollection: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult<PHAsset>?
//通過PHAsset的burstIdentifier獲取PHAsset,burstIdentifier是連拍模式才會有的id,通過該id可以獲取連拍模式的所有照片
open class func fetchAssets(withBurstIdentifier burstIdentifier: String, options: PHFetchOptions?) -> PHFetchResult<PHAsset>
// Fetches PHAssetSourceTypeUserLibrary assets by default (use includeAssetSourceTypes option to override)
open class func fetchAssets(with options: PHFetchOptions?) -> PHFetchResult<PHAsset>
//獲取對應(yīng)類型的PHAsset
open class func fetchAssets(with mediaType: PHAssetMediaType, options: PHFetchOptions?) -> PHFetchResult<PHAsset>
// assetURLs are URLs retrieved from ALAsset's ALAssetPropertyAssetURL
@available(iOS, introduced: 8.0, deprecated: 11.0, message: "Will be removed in a future release")
open class func fetchAssets(withALAssetURLs assetURLs: [URL], options: PHFetchOptions?) -> PHFetchResult<PHAsset>
其中fetchAssetsInAssetCollection:options:方法可以獲取資源集合中的所有asset對象惰蜜。每個方法中的 PHFetchOptions參數(shù)昂拂,是獲取asset對象的一些配置,我們可以設(shè)置獲取asset的條件,比如獲取哪種資源抛猖,如何分類格侯。獲取的時候,如果該參數(shù)為空财著,則使用系統(tǒng)的默認值联四,當(dāng)我們調(diào)用如上所示方法獲取時,可以直接傳nil撑教。
// Fetch asset collections of a single type matching the provided local identifiers (type is inferred from the local identifiers)
//通過LocalIdentifier和option獲取相冊
open class func fetchAssetCollections(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
// Fetch asset collections of a single type and subtype provided (use PHAssetCollectionSubtypeAny to match all subtypes)
//通過相冊類型獲取相冊
open class func fetchAssetCollections(with type: PHAssetCollectionType, subtype: PHAssetCollectionSubtype, options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
// Smart Albums are not supported, only Albums and Moments
//獲取包含對應(yīng)PHAsset的相冊朝墩,Smart Albums(系統(tǒng)分配智能的相冊,PHAssetCollectionType枚舉中選擇)不支持
open class func fetchAssetCollectionsContaining(_ asset: PHAsset, with type: PHAssetCollectionType, options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
// assetGroupURLs are URLs retrieved from ALAssetGroup's ALAssetsGroupPropertyURL
//通過URL獲取相冊驮履,assetGroupURLs是通過AssetsLibrary獲取的URLs
open class func fetchAssetCollections(withALAssetGroupURLs assetGroupURLs: [URL], options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
//獲取一個集合中PHAssetCollectionType 為moment的相冊
open class func fetchMoments(inMomentList momentList: PHCollectionList, options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
//獲取所有PHAssetCollectionType為moment的相冊
open class func fetchMoments(with options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
PHCollectionList
// A PHAssetCollectionTypeMoment will be contained by a PHCollectionListSubtypeMomentListCluster and a PHCollectionListSubtypeMomentListYear
// Non-moment PHAssetCollections will only be contained by a single collection list
open class func fetchCollectionListsContaining(_ collection: PHCollection, options: PHFetchOptions?) -> PHFetchResult<PHCollectionList>
// Fetch collection lists of a single type matching the provided local identifiers (type is inferred from the local identifiers)
open class func fetchCollectionLists(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHCollectionList>
// Fetch asset collections of a single type and subtype provided (use PHCollectionListSubtypeAny to match all subtypes)
open class func fetchCollectionLists(with collectionListType: PHCollectionListType, subtype: PHCollectionListSubtype, options: PHFetchOptions?) -> PHFetchResult<PHCollectionList>
open class func fetchMomentLists(with momentListSubtype: PHCollectionListSubtype, containingMoment moment: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult<PHCollectionList>
open class func fetchMomentLists(with momentListSubtype: PHCollectionListSubtype, options: PHFetchOptions?) -> PHFetchResult<PHCollectionList>
PHAsset
PHAsset是用來獲取圖片和視頻文件的元數(shù)據(jù)鱼辙,相當(dāng)于以前的 ALAsset,但比起ALAsset,PhotoKit 提供了額外的關(guān)于用戶資源的元數(shù)據(jù)廉嚼,而這些數(shù)據(jù)在以前使用 ALAssetsLibrary 框架中是沒有辦法訪問玫镐,或者很難訪問到倒戏。我們可以用PHAsset保存圖片和視頻資源對象, 然后展示或者修改它.它有幾個重要屬性:
mediaType
:資源類型,圖片或者音頻或視頻
mediaSubtypes
:圖片又包含全景圖(Panorama)、HDR圖片恐似、屏幕截圖杜跷、livePhoto ,我們可以使用照片資源的 mediaSubtypes 屬性驗證資源庫中的圖像在捕捉時是否開啟了 HDR矫夷,拍攝時是否使用了相機應(yīng)用的全景模式.
Creation date
創(chuàng)建時間
Location
定位
Favorite
布爾值葛闷,用戶是否標(biāo)記資源為"收藏",我們平時瀏覽照片或視頻双藕,在下方點??就表示收藏這張圖淑趾。
hidden
要驗證一個資源是否被用戶標(biāo)記為收被隱藏,只要檢查 PHAsset 實例的 hidden 屬性即可忧陪。
sourceType
: 資源可以來源自用戶相冊扣泊、iCloud、iTunes同步
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)記的資源辨萍。
localIdentifier
Photos 框架中的根類PHObject只有一個公開接口localIdentifier,是對象唯一唯一標(biāo)志符.PHObject實現(xiàn)了-isEqual 和-hash方法.可以直接使用localIdentifier屬性對PHObject及其子類對象進行對比是否同一個對象棋恼。
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 //包含所有類型
}
estimatedAssetCount
:估算的asset數(shù)量
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];
PHFetchResult
類似數(shù)組,存儲獲取到asset對象集合舷蒲。同步快速獲取結(jié)果,即使結(jié)果集很大耸袜,框架也能保證獲取速度. 因為它不會一次性將所有結(jié)果放進內(nèi)存,而是按需批量加載,可以用類似 NSArray 的接口來訪問PHFetchResult結(jié)果內(nèi)的集合牲平。
資源對象的增刪改
(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更新操作。
PHPhotoLibrary.shared().performChanges({
//新增、修改或刪除操作
}) { (success, error) in
//新增底挫、修改或刪除完成
}
創(chuàng)建一個新資源只要用 creationRequestForAssetFromXXX(...)工廠方法恒傻,來創(chuàng)建變化請求,并傳入資源圖像數(shù)據(jù) (或一個 URL)建邓。如果你需要對新建的資源做額外的修改盈厘,你可以用創(chuàng)建變化請求的placeholderForCreatedAsset屬性。它會返回一個可用的 placeholder 來代替“真實的” PHAsset 引用.
PHPhotoLibrary
系統(tǒng)中PHPhotoLibrary單例對象 是用來維護用戶照片庫涝缝。當(dāng)我們需要編輯資源對象元數(shù)據(jù)扑庞、資源內(nèi)容譬重、或者插入新的資源對象等拒逮,都可以借助通過PHPhotoLibrary單例對象執(zhí)行block,block中創(chuàng)建我們指定的請求對象(比如PHAssetChangeRequest,PHAssetCollectionChangeRequest, PHCollectionListChangeRequest的對象)臀规。photoLibraryDidChange(changeInfo: PHChange!)中進行.
協(xié)議PHPhotoLibraryChangeObserver
PHPhotoLibraryChangeObserver協(xié)議能讓我們知道照片相冊庫中的改變滩援。Photos會發(fā)送系統(tǒng)圖片改變的消息,我們可以遵守PHPhotoLibraryChangeObserver協(xié)議塔嬉,并通過 PHPhotoLibrary的registerChangeObserver方法將對象注冊為觀察者玩徊,時時接收照片改變的消息。
PHChange
PHphoto框架會提供給我們PHChange對象谨究,我們可以調(diào)用changeDetailsForObject或者changeDetailsForFetchResult 方法恩袱,它返回給我們一個PHObjectChangeDetails對象,是對最新的照片實體對象的引用胶哲,可以告訴我們對象的圖像數(shù)據(jù)是否曾變化過畔塔、對象是否曾被刪除過。
請求圖片
PHImageManager.default().requestImage(for: <#T##PHAsset#>, targetSize: <#T##CGSize#>, contentMode: <#T##PHImageContentMode#>, options: <#T##PHImageRequestOptions?#>, resultHandler: <#T##(UIImage?, [AnyHashable : Any]?) -> Void#>)
targetSize
: 返回圖片的尺寸
contentMode
:決定了照片應(yīng)該以按比例縮放還是按比例填充的方式放到目標(biāo)大小內(nèi)鸯屿。
options
: PHImageRequestOptions類用于定制請求澈吨。上面的方法返回指定尺寸的圖像,如果你僅僅指定必要的參數(shù)而沒有對 options 進行配置的話寄摆,返回的圖像尺寸將會是原始圖像的尺寸谅辣。或者婶恼,你指定的尺寸很小桑阶,這時候會按照你的要求來返回接近該尺寸的圖像。
PHImageRequestOptions
synchronous
: 指定請求是否同步執(zhí)行勾邦。
resizeMode
: 對請求的圖像怎樣縮放蚣录。有三種選擇:None,不縮放检痰;Fast包归,盡快地提供接近或稍微大于要求的尺寸;Exact,精準(zhǔn)提供要求的尺寸公壤。
deliveryMode
: 圖像質(zhì)量换可。有三種值:Opportunistic,在速度與質(zhì)量中均衡厦幅;HighQualityFormat沾鳄,不管花費多長時間,提供高質(zhì)量圖像确憨;FastFormat译荞,以最快速度提供好的質(zhì)量。
normalizedCropRect
: 用于對原始尺寸的圖像進行裁剪休弃,基于比例坐標(biāo)吞歼。只在 resizeMode 為 Exact 時有效。
resizeMode
默認是 None塔猾,這也造成了返回圖像尺寸與要求尺寸不符篙骡。這點需要注意。要返回一個指定尺寸的圖像需要避免兩層陷阱:一定要指定 options 參數(shù)丈甸,resizeMode 不能為 None糯俗。
是否裁剪圖片由 targetSize、contentMode來控制睦擂,裁剪的尺寸由targetSize得湘、contentMode、resizeMode指定顿仇。