在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 照片框架
與四軸無(wú)人機(jī)的通訊
在沙盒中編寫(xiě)腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測(cè)試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動(dòng)開(kāi)發(fā)
Collection View 動(dòng)畫(huà)
截圖測(cè)試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個(gè)完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動(dòng)布局工具箱
動(dòng)畫(huà)
為 iOS 7 重新設(shè)計(jì) App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動(dòng)畫(huà)解釋
響應(yīng)式 Android 應(yīng)用
初識(shí) TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項(xiàng)目介紹
Swift 的強(qiáng)大之處
測(cè)試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計(jì)優(yōu)雅的移動(dòng)游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動(dòng)畫(huà)
常見(jiàn)的后臺(tái)實(shí)踐
糟糕的測(cè)試
避免濫用單例
數(shù)據(jù)模型和模型對(duì)象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場(chǎng)
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計(jì)的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計(jì)
置換測(cè)試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無(wú)人機(jī)項(xiàng)目
Mach-O 可執(zhí)行文件
UI 測(cè)試
值對(duì)象
活動(dòng)追蹤
依賴注入
Swift
項(xiàng)目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測(cè)試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場(chǎng)
游戲
調(diào)試核對(duì)清單
View Controller 容器
學(xué)無(wú)止境
XCTest 測(cè)試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動(dòng)畫(huà)
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲(chǔ)
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺(jué)
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫(kù)支持
Fetch 請(qǐng)求
導(dǎo)入大數(shù)據(jù)集
iOS 開(kāi)發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語(yǔ)言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識(shí)別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過(guò)程

照片框架

介紹

每天,用 iPhone 拍攝的照片數(shù)量超過(guò)了任何相機(jī)。每年 iOS 設(shè)備上的顯示效果變得越來(lái)越好,回到 iPad 剛出現(xiàn)還沒(méi)有 Retina 顯示屏的時(shí)代,大屏幕的殺手級(jí)功能之一就是可以展示用戶照片和瀏覽器照片庫(kù)。自從相機(jī)成為 iPhone 最重要和最受歡迎的功能開(kāi)始,對(duì)能管理和加工用戶照片庫(kù)中寶貴的照片的應(yīng)用程序和工具就有著巨大的需求。

直到 2014 年夏天前,開(kāi)發(fā)者只能用 AssetsLibrary 框架訪問(wèn)日益增長(zhǎng)的用戶的照片庫(kù)。幾年以來(lái),相機(jī)應(yīng)用和照片應(yīng)用發(fā)生了顯著的變化,增加了許多新特性,包括按時(shí)刻來(lái)組織照片的方式。但與此同時(shí),AssetsLibrary 框架卻沒(méi)有跟上步伐。

隨著 iOS 8 的到來(lái),蘋(píng)果給我們提供了一個(gè)現(xiàn)代化的框架 —— PhotoKit,它比 AssetsLibrary 表現(xiàn)更好,并且擁有讓?xiě)?yīng)用和設(shè)備照片庫(kù)無(wú)縫工作的特性。

概要

我們將從框架對(duì)象模型的鳥(niǎo)瞰圖開(kāi)始:實(shí)體和實(shí)體間的關(guān)系,獲取實(shí)體的實(shí)例,以及使用獲取的結(jié)果進(jìn)行工作。

除此之外,我們的講解還會(huì)涉及到一些在使用 AssetsLibrary 時(shí),尚未對(duì)開(kāi)發(fā)者開(kāi)放的資源元數(shù)據(jù)

然后我們會(huì)討論加載資源的圖像數(shù)據(jù):過(guò)程本身,大量可用的選項(xiàng),一些陷阱和邊界案例。

最后,我們會(huì)談?wù)勍ㄟ^(guò)外部參與者來(lái)觀察照片庫(kù)的變化,學(xué)習(xí)如何創(chuàng)建和提交我們自己修改的改變。

PhotoKit 對(duì)象模型

PhotoKit 定義了與系統(tǒng)的 Photos 應(yīng)用內(nèi)展現(xiàn)給用戶的模型對(duì)象相一致的實(shí)體圖表。這些照片實(shí)體都是輕量級(jí)的不可變對(duì)象。所有的 PhotoKit 對(duì)象都是繼承自 PHObject 抽象基類,其公共接口只提供了一個(gè) localIdentifier 屬性。

PHAsset 表示用戶照片庫(kù)中一個(gè)單獨(dú)的資源,用以提供資源的元數(shù)據(jù)。

成組的資源叫做資源集合,用 PHAssetCollection 類表示。一個(gè)單獨(dú)的資源集合可以是照片庫(kù)中的一個(gè)相冊(cè)或者一個(gè)時(shí)刻,或者是一個(gè)特殊的“智能相冊(cè)”。這種智能相冊(cè)包括所有的視頻集合,最近添加的項(xiàng)目,用戶收藏,所有連拍照片等等。PHAssetCollectionPHCollection 的子類。

PHCollectionList 表示一組的 PHCollections。因?yàn)樗旧砭褪?PHCollection,所以集合列表可以包含其他集合列表,它們?cè)试S復(fù)雜的集合繼承。實(shí)際上,我們可以在照片應(yīng)用的時(shí)刻欄目中看到它:照片 --- 時(shí)刻 --- 精選 --- 年度,就是一個(gè)例子。

獲取 (Fetch) 照片實(shí)體

獲取 vs. 枚舉

那些熟悉 AssetsLibrary 框架的開(kāi)發(fā)者可能會(huì)記得 AssetsLibrary 可以用一些特定屬性來(lái)找到需要的資源,其中一個(gè)必須枚舉用戶資源庫(kù)來(lái)獲得匹配的資源。不得不承認(rèn),這個(gè) API 雖然提供了一些縮小搜索域的方法,但還是十分低效。

而與之形成鮮明對(duì)比,PhotoKit 實(shí)體的實(shí)例是通過(guò)獲取得到的。那些熟悉 Core Data 的人,會(huì)覺(jué)得和 PhotoKit 在概念和描述都比較接近。

獲取請(qǐng)求

獲取操作是由上面描述的實(shí)體的類方法實(shí)現(xiàn)的。要使用哪個(gè)類/方法,取決于問(wèn)題所在范圍和你展示與遍歷照片庫(kù)的方式。所有獲取方法的命名都是相似的:class func fetchXXX(..., options: PHFetchOptions) -> PHFetchResult 。options 參數(shù)給了我們一個(gè)對(duì)結(jié)果進(jìn)行過(guò)濾和排序的途徑,這和 NSFetchRequestpredicatesortDescriptors 參數(shù)類似。

獲取結(jié)果

你可能已經(jīng)注意到了這些獲取操作不是異步的。它們返回了一個(gè) PHFetchResult 對(duì)象,可以用類似 NSArray 的接口來(lái)訪問(wèn)結(jié)果內(nèi)的集合。它會(huì)按需動(dòng)態(tài)加載內(nèi)容并且緩存最近請(qǐng)求的內(nèi)容。這個(gè)行為和設(shè)置了 batchSize 屬性的 NSFetchRequest 返回的結(jié)果數(shù)組相似。對(duì)于 PHFetchResult 來(lái)說(shuō),沒(méi)有辦法用參數(shù)來(lái)指定這個(gè)行為,但是官網(wǎng)文檔保證 “即使在處理大量的返回結(jié)果時(shí),依然能夠有最好的表現(xiàn)”。

就算滿足請(qǐng)求的照片庫(kù)內(nèi)容發(fā)生了改變,獲取方法所返回的 PHFetchResult 對(duì)象是不會(huì)自動(dòng)更新。在后面的小節(jié)中,我們會(huì)介紹如何對(duì)返回的 PHFetchResult 對(duì)象的改變進(jìn)行觀察并處理更新內(nèi)容。

臨時(shí)集合 (Transient Collections)

你可能會(huì)發(fā)現(xiàn)你已經(jīng)設(shè)計(jì)了一個(gè)可以操作資源集合的組件,并且你還希望它能夠處理任意一組的資源。PhotoKit 通過(guò)臨時(shí)資源集合,讓我們可以輕松做到這點(diǎn)。

你可以通過(guò) PHAsset 對(duì)象數(shù)組或是包含資源的 PHFetchResult 對(duì)象來(lái)創(chuàng)建臨時(shí)資源集合。創(chuàng)建的操作在 PHAssetCollectiontransientAssetCollectionWithAssets(...)transientAssetCollectionWithFetchResult(...) 工廠方法內(nèi)完成。這些方法創(chuàng)建出來(lái)的對(duì)象可以像其它的 PHAssetCollection 對(duì)象一樣使用。盡管如此,這些集合不會(huì)被存儲(chǔ)到用戶照片庫(kù),自然也不會(huì)在照片應(yīng)用中展示出來(lái)。

和資源集合相似,你可以用 PHCollectionList 中的 transientCollectionListWithXXX(...) 工廠方法來(lái)創(chuàng)建臨時(shí)集合列表。

當(dāng)你要合并兩個(gè)獲取請(qǐng)求時(shí),你就會(huì)發(fā)現(xiàn)這個(gè)東西非常有用。

照片元數(shù)據(jù)

正如文章開(kāi)頭提到的,PhotoKit 提供了額外的關(guān)于用戶資源的元數(shù)據(jù),而這些數(shù)據(jù)在以前使用 ALAssetsLibrary 框架中是沒(méi)有辦法訪問(wèn),或者很難訪問(wèn)到。

HDR 和全景照片

你可以使用照片資源的 mediaSubtypes 屬性驗(yàn)證資源庫(kù)中的圖像在捕捉時(shí)是否開(kāi)啟了 HDR,拍攝時(shí)是否使用了相機(jī)應(yīng)用的全景模式。

收藏和隱藏資源

要驗(yàn)證一個(gè)資源是否被用戶標(biāo)記為收藏或被隱藏,只要檢查 PHAsset 實(shí)例的 favoritehidden 屬性即可。

連拍模式照片

對(duì)于一個(gè)資源,如果其 PHAssetrepresentsBurst 屬性為 true,則表示這個(gè)資源是一系列連拍照片中的代表照片 (多張照片是在用戶按住快門(mén)時(shí)拍攝的)。它還有一個(gè)屬性是 burstIdentifier,如果想要獲取連拍照片中的剩余的其他照片,可以通過(guò)將這個(gè)值傳入 fetchAssetsWithBurstIdentifier(...) 方法來(lái)獲取。

用戶可以在連拍的照片中做標(biāo)記;此外,系統(tǒng)也會(huì)自動(dòng)用各種試探來(lái)標(biāo)記用戶可能會(huì)選擇的潛在代表照片。這個(gè)元數(shù)據(jù)是可以通過(guò) PHAssetburstSelectionTypes 屬性來(lái)訪問(wèn)。這個(gè)屬性是用三個(gè)常量組成的位掩碼:.UserPick 表示用戶手動(dòng)標(biāo)記的資源,.AutoPick 表示用戶可能標(biāo)記的潛在資源,.None 表示沒(méi)有標(biāo)記的資源。

http://wiki.jikexueyuan.com/project/objc/images/21-12.jpg" alt="" />

這個(gè)屏幕快照顯示了,照片應(yīng)用是如何在連拍的照片中自動(dòng)標(biāo)記用戶可能標(biāo)記的潛在資源。

照片加載

在處理用戶照片庫(kù)的過(guò)去幾年中,開(kāi)發(fā)者創(chuàng)造了上百 (如果沒(méi)有上千) 的小技巧來(lái)提高照片加載和展示的效率。這些技巧處理請(qǐng)求的派發(fā)和取消,圖像大小的修改和裁剪,緩存等等。PhotoKit 提供了一個(gè)可以用更加便捷和現(xiàn)代的 API 做了所有這些操作的類:PHImageManager 。

請(qǐng)求圖像

圖像請(qǐng)求是通過(guò) requestImageForAsset(...) 方法派發(fā)的。這個(gè)方法接受一個(gè) PHAsset,可以設(shè)置返回圖像的大小和圖像的其它可選項(xiàng) (通過(guò) PHImageRequestOptions 參數(shù)對(duì)象設(shè)置),以及結(jié)果回調(diào) (result handler)。這個(gè)方法的返回值可以用來(lái)在所請(qǐng)求的數(shù)據(jù)不再被需要時(shí)取消這個(gè)請(qǐng)求。

圖像的尺寸和裁剪

奇怪的是,對(duì)返回圖像的尺寸定義和裁剪的參數(shù)是分布在兩個(gè)地方的。targetSizecontentMode 這倆參數(shù)會(huì)被直接傳入 requestImageForAsset(...) 方法內(nèi)。這個(gè) content Mode 和 UIView 的 contentMode 參數(shù)類似,決定了照片應(yīng)該以按比例縮放還是按比例填充的方式放到目標(biāo)大小內(nèi)。注意:如果不對(duì)照片大小進(jìn)行修改或裁剪,那么方法參數(shù)是 PHImageManagerMaximumSizePHImageContentMode.Default 。

此外,PHImageRequestOptions 還提供了一些方式來(lái)確定圖像管理器該以怎樣的方式來(lái)重新設(shè)置圖像大小。resizeMode 屬性可以設(shè)置為 .Exact (返回圖像必須和目標(biāo)大小相匹配),.Fast (比 .Exact 效率更高,但返回圖像可能和目標(biāo)大小不一樣) 或者 .None。還有個(gè)值得一提的是,normalizedCroppingMode 屬性讓我們確定圖像管理器應(yīng)該如何裁剪圖像。注意:如果設(shè)置了 normalizedcroppingMode 的值,那么 resizeMode 需要設(shè)置為 .Exact。

請(qǐng)求遞送和進(jìn)度

默認(rèn)情況下,如果圖像管理器決定要用最優(yōu)策略,那么它會(huì)在將圖像的高質(zhì)量版本遞送給你之前,先傳遞一個(gè)較低質(zhì)量的版本。你可以通過(guò) deliveryMode 屬性來(lái)控制這個(gè)行為;上面所描述的默認(rèn)行為的值為 .Opportunistic。如果你只想要高質(zhì)量的圖像,并且可以接受更長(zhǎng)的加載時(shí)間,那么將屬性設(shè)置為 .HighQualityFormat。如果你想要更快的加載速度,且可以犧牲一點(diǎn)圖像質(zhì)量,那么將屬性設(shè)置為 .FastFormat。

你可以使用 PHImageRequestOptionssynchronous 屬性,讓 requestImage... 系列的方法變成同步操作。注意:當(dāng) synchronous 設(shè)為 true 時(shí),deliveryMode 屬性就會(huì)被忽略,并被當(dāng)作 .HighQualityFormat 來(lái)處理。

在設(shè)置這些參數(shù)時(shí),一定要考慮到你的一些用戶有可能開(kāi)啟了 iCloud 照片庫(kù),這點(diǎn)非常重要。PhotoKit 的 API 不一定會(huì)對(duì)設(shè)備的照片和 iCloud 上照片進(jìn)行區(qū)分 —— 它們都用同一個(gè) requestImage 方法來(lái)加載。這意味著任意一個(gè)圖像請(qǐng)求都有可能是一個(gè)通過(guò)蜂窩網(wǎng)絡(luò)來(lái)進(jìn)行的非常緩慢的網(wǎng)絡(luò)請(qǐng)求。當(dāng)你要用 .HighQualityFormat 或者做一個(gè)同步請(qǐng)求的時(shí)候,要牢記這個(gè)。注意:如果你想要確保請(qǐng)求不經(jīng)過(guò)網(wǎng)絡(luò),可以將 networkAccessAllowed 設(shè)為 false 。

另一個(gè)和 iCloud 相關(guān)的屬性是 progressHandler。你可以將它設(shè)為一個(gè) PHAssetImageProgressHandler 的 block,當(dāng)從 iCloud 下載照片時(shí),它就會(huì)被圖像管理器自動(dòng)調(diào)用。

資源版本

PhotoKit 允許應(yīng)用對(duì)照片進(jìn)行無(wú)損的修改。對(duì)編輯過(guò)的照片,系統(tǒng)會(huì)對(duì)單獨(dú)保存一份原始照片的拷貝和針對(duì)應(yīng)用的調(diào)整數(shù)據(jù)。當(dāng)用圖像管理器獲取資源時(shí),你可以指定哪個(gè)版本的圖像資源應(yīng)該通過(guò) result handler 被遞送。這可以通過(guò)設(shè)置 version 屬性來(lái)做到:.Current 會(huì)遞送包含所有調(diào)整和修改的圖像;.Unadjusted 會(huì)遞送未被施加任何修改的圖像;.Original 會(huì)遞送原始的、最高質(zhì)量的格式的圖像 (例如 RAW 格式的數(shù)據(jù)。而當(dāng)將屬性設(shè)置為 .Unadjusted 時(shí),會(huì)遞送一個(gè) JPEG)。

你可以在 Sam Davies 的文章《照片擴(kuò)展》中,閱讀框架中更多關(guān)于這方面的內(nèi)容。

結(jié)果回調(diào) (result handler)

結(jié)果回調(diào)是一個(gè)包含了一個(gè) UIImage 變量和一個(gè) info 字典作為參數(shù)的 block。根據(jù)參數(shù)和請(qǐng)求的選項(xiàng),在請(qǐng)求的整個(gè)生命周期,它可以被圖像管理器多次調(diào)用。

info 字典提供了關(guān)于當(dāng)前請(qǐng)求狀態(tài)的信息,比如:

  • 圖像是否必須從 iCloud 請(qǐng)求 (如果你初始化時(shí)將 networkAccessAllowed 設(shè)置成 false,那么就必須重新請(qǐng)求圖像) —— PHImageResultIsInCloudKey 。
  • 當(dāng)前遞送的 UIImage 是否是最終結(jié)果的低質(zhì)量格式。當(dāng)高質(zhì)量圖像正在下載時(shí),這個(gè)可以讓你給用戶先展示一個(gè)預(yù)覽圖像 —— PHImageResultIsDegradedKey。
  • 請(qǐng)求 ID (可以便捷的取消請(qǐng)求),以及請(qǐng)求是否已經(jīng)被取消 —— PHImageResultRequestIDKeyPHImageCancelledKey。
  • 如果沒(méi)有圖像提供給 result handler,字典內(nèi)還會(huì)有一個(gè)錯(cuò)誤信息 —— PHImageErrorKey。

這些值可以讓你更新你的 UI 來(lái)告知用戶,和上面討論到的 progressHandler 一起,來(lái)表示出它們的加載狀態(tài)。

緩存

當(dāng)圖像即將要展示在屏幕上時(shí),比如當(dāng)要在一組滾動(dòng)的 collection 視圖上展示大量的資源圖像的縮略圖時(shí),預(yù)先將一些圖像加載到內(nèi)存中有時(shí)是非常有用的。PhotoKit 提供了一個(gè) PHImageManager 的子類來(lái)處理這種特定的使用場(chǎng)景 —— PHImageCachingManager。

PHImageCachingManager 提供了一個(gè)關(guān)鍵方法 —— startCachingImagesForAssets(...)。你傳入一個(gè) PHAssets 類型的數(shù)組,一些請(qǐng)求參數(shù),以及一些請(qǐng)求單個(gè)圖像時(shí)即將用到的可選項(xiàng)。此外,還有一些方法可以讓你通知緩存管理器來(lái)停止緩存特定資源列表,以及停止緩存所有圖像。

allowsCachingHighQualityImages 屬性可以讓你指定圖像管理器是否應(yīng)該準(zhǔn)備高質(zhì)量圖像。當(dāng)緩存一個(gè)較短和不變的資源列表時(shí),默認(rèn) true 的屬性表現(xiàn)很好。但當(dāng)要在 collection 視圖上快速滑動(dòng)時(shí)做緩存操作的話,最好將它設(shè)置成 false 。

注意:以我的經(jīng)驗(yàn),當(dāng)用戶正在有大量資源的 collection 視圖上極其快速的滑動(dòng)時(shí),使用緩存管理器會(huì)損害滑動(dòng)的表現(xiàn)效果。為這種特定的使用場(chǎng)景定制一個(gè)緩存行為是極其重要的。緩存窗口的大小,移動(dòng)緩存窗口的時(shí)機(jī)和頻率,allowsCachingHighQualityImages 的屬性值 —— 這些參數(shù)都要在目標(biāo)硬件上的真實(shí)照片庫(kù)中仔細(xì)地調(diào)節(jié),并測(cè)試表現(xiàn)效果。更進(jìn)一步,你可以考慮在用戶行為的基礎(chǔ)上,動(dòng)態(tài)的設(shè)置這些參數(shù)。

請(qǐng)求圖像數(shù)據(jù)

最后,除了請(qǐng)求普通的 UIImage 之外,PHImageManager 提供了另一個(gè)方法可以返回 NSData 對(duì)象類型的資源數(shù)據(jù),包括它的通用類型標(biāo)識(shí)符,圖像的展示方向。這個(gè)方法返回了這個(gè)資源的最多的信息。

滄海桑田,萬(wàn)物變遷

我們已經(jīng)討論了在用戶照片庫(kù)中請(qǐng)求資源的元數(shù)據(jù),但是到目前為止,我們沒(méi)提及如何更新我們獲取的數(shù)據(jù)。照片庫(kù)本質(zhì)上是一大堆可變的狀態(tài),而第一節(jié)中提到的照片實(shí)體是不可變的對(duì)象。PhotoKit 可以讓你接收你需要的、關(guān)于照片庫(kù)變動(dòng)的所有信息,以正確更新你的緩存狀態(tài)。

觀察變化

首先,你需要通過(guò)共享的 PHPhotoLibrary 對(duì)象,用 registerChangeObserver(...) 方法注冊(cè)一個(gè)變化觀察者 (這個(gè)觀察者要遵從 PHPhotoLibraryChangeObserver 協(xié)議)。只要另一個(gè)應(yīng)用或者用戶在照片庫(kù)中做的修改影響了你在變化前獲取的任何資源或資源集合的話,變化觀察者的 photoLibraryDidChange(...) 方法都會(huì)被調(diào)用。這個(gè)方法只有一個(gè) PHChange 類型的參數(shù),你可以用它來(lái)驗(yàn)證這些變化是否和你所感興趣的獲取對(duì)象有關(guān)聯(lián)。

更新獲取的結(jié)果

PHChange 提供了幾個(gè)方法,讓你可以通過(guò)傳入任何你感興趣的 PHObject 對(duì)象或 PHFetchResult 對(duì)象來(lái)追蹤它們的變化。這幾個(gè)方法是 changeDetailsForObject(...)changeDetailsForFetchResult(...) 。如果沒(méi)有任何變化,這些方法會(huì)返回 nil,否則你可以借助 PHObjectChangeDetailsPHFetchResultChangeDetails 對(duì)象來(lái)觀察這些變化。

PHObjectChangeDetails 提供了一個(gè)對(duì)最新的照片實(shí)體對(duì)象的引用,以及告訴你對(duì)象的圖像數(shù)據(jù)是否曾變化過(guò)、對(duì)象是否曾被刪除過(guò)的布爾值。

PHFetchResultChangeDetails 封裝了施加在你之前通過(guò)獲取所得到的 PHFetchResult 上的變化的信息。PHFetchResultChangeDetails 是為了盡可能簡(jiǎn)化 CollectionView 或 TableView 的更新操作而設(shè)計(jì)的。它的屬性恰好映射到你在使用一個(gè)典型的 CollectionView 的 update handler 時(shí)所需要的信息。注意,若要正確的更新 UITableView/UICollectionView,你必須以正確順序來(lái)處理變化,那就是:RICE —— removedIndexes,insertedIndexes,changedIndexes,enumerateMovesWithBlock (如果 hasMovestrue 的話)。另外,PHFetchResultChangeDetailshasIncrementalChanges 屬性可以被設(shè)置成 false,這意味著舊的獲取結(jié)果應(yīng)該全部被新的值代替。這種情況下,你應(yīng)該調(diào)用 UITableView/UICollectionViewreloadData。

注意:沒(méi)有必要以集中的方式處理變化。如果你應(yīng)用中的多個(gè)組件需要處理照片實(shí)體,那么它們每個(gè)都要有自己的 PHPhotoLibraryChangeObserver 。接著組件就能靠自己查詢 PHChange 對(duì)象,檢測(cè)是否需要 (以及如何) 更新它們自己的狀態(tài)。

隨風(fēng)而變

現(xiàn)在我們已經(jīng)知道了如何觀察用戶和其他應(yīng)用造成的變化,我們來(lái)嘗試一下自己進(jìn)行改變。

改變存在的對(duì)象

用 PhotoKit 在照片庫(kù)做改變,說(shuō)到底其實(shí)是先創(chuàng)建了一個(gè)鏈接到某個(gè)資源或者資源集合的變化請(qǐng)求對(duì)象,再設(shè)置請(qǐng)求對(duì)象的相關(guān)屬性或調(diào)用合適的方法來(lái)描述你想要提交的變化。這個(gè)必須通過(guò) performChanges(...) 方法,在提交到共享的 PHPhotoLibrary 的 block 內(nèi)完成。注意:你需要準(zhǔn)備好在 performChanges 方法的 completion block 里處理失敗的情況。雖然處理的是能被多個(gè)參與者 (如你的應(yīng)用,用戶,其他應(yīng)用,照片擴(kuò)展等) 改變的狀態(tài),但這個(gè)方式能提供安全性,也相對(duì)易用。

想要修改資源,需要?jiǎng)?chuàng)建一個(gè) PHAssetChangeRequest 。然后你就可以修改創(chuàng)建創(chuàng)建日期,資源位置,以及是否將隱藏資源,是否將資源看做用戶收藏等。此外,你還可以從用戶的庫(kù)里刪除資源。

類似地,若要修改資源集合或集合列表,需要?jiǎng)?chuàng)建一個(gè) PHAssetCollectionChangeRequestPHCollectionListChangeRequest 對(duì)象。然后你就可以修改集合標(biāo)題,添加或刪除集合成員,或者完全刪除集合。

在你的變化提交到用戶照片庫(kù)前,系統(tǒng)會(huì)向用戶展示一個(gè)明確的獲取權(quán)限的警告框。

創(chuàng)建新對(duì)象

創(chuàng)建一個(gè)新資源的做法和修改已存在的資源類似。只要用 creationRequestForAssetFromXXX(...) 工廠方法,來(lái)創(chuàng)建變化請(qǐng)求,并傳入資源圖像數(shù)據(jù) (或一個(gè) URL)。如果你需要對(duì)新建的資源做額外的修改,你可以用創(chuàng)建變化請(qǐng)求的 placeholderForCreatedAsset 屬性。它會(huì)返回一個(gè)可用的 placeholder 來(lái)代替“真實(shí)的” PHAsset 引用。

結(jié)論

我已經(jīng)討論了 PhotoKit 的基礎(chǔ)知識(shí),但仍然還有非常多的東西等著我們?nèi)グl(fā)掘。你可以通過(guò)查看示例的各處的代碼,觀看 WWDC session 視頻學(xué)習(xí)更多內(nèi)容,發(fā)掘更深的知識(shí),然后寫(xiě)一些自己的代碼!PhotoKit 為 iOS 開(kāi)發(fā)者開(kāi)啟了通往新世界可能性,在未來(lái)的數(shù)月或者數(shù)年里,我們肯定會(huì)看到更多基于這個(gè)基礎(chǔ)構(gòu)建的富有創(chuàng)造性的優(yōu)秀產(chǎn)品。

上一篇:結(jié)構(gòu)體和值類型下一篇:XPC