Extension概述
眾所周知,基于iOS系統(tǒng)的安全性考慮高帖,其應(yīng)用的數(shù)據(jù)存儲(chǔ)是通過(guò)沙盒模式進(jìn)行的,要實(shí)現(xiàn)應(yīng)用之間的數(shù)據(jù)共享十分困難畦粮,功能共享就更加棘手散址。在iOS8系統(tǒng)中,apple為我們提供了一個(gè)革命性的功能:擴(kuò)展宣赔。我們可以通過(guò)擴(kuò)展來(lái)使app間數(shù)據(jù)甚至功能進(jìn)行共享预麸。
App Extension出現(xiàn)后,突破了兩個(gè)重要的iOS限制儒将,那就是:由Open In系統(tǒng)創(chuàng)建的應(yīng)用程序之間不必要的數(shù)據(jù)復(fù)制和無(wú)法替換蘋果鍵盤吏祸。
然而,其中有一個(gè)最可能的誤解需要澄清一下钩蚊,就是iOS 8 App Extensions不同于Android Indents贡翘,Ars Technica網(wǎng)站撰稿人Andrew Cunningham這樣寫道。根據(jù)Google的描述:
Intent提供了一種機(jī)制砰逻,用于不同應(yīng)用程序代碼之間的后期運(yùn)行時(shí)綁定鸣驱。它主要用來(lái)啟動(dòng)Activities,因此可以將它看作是Activities之間的粘合劑蝠咆。從本質(zhì)上講踊东,它是一個(gè)無(wú)源數(shù)據(jù)結(jié)構(gòu),存放要執(zhí)行動(dòng)作的抽象描述刚操。
雖然Extension在很多情況下與Intent沒(méi)有什么不同闸翅,但在iOS 8中,App Extension系統(tǒng)的整體設(shè)計(jì)使得它與Intent有很大的不同菊霜。
Extension的生命周期
正如蘋果文檔中的描述坚冀,Extension是通過(guò)“包含應(yīng)用程序(containing app)”提供的專門的二進(jìn)制文件。包含應(yīng)用程序只負(fù)責(zé)提供Extension鉴逞,后者是獨(dú)立運(yùn)行的遗菠。盡管如此联喘,一個(gè)iOS包含應(yīng)用程序?qū)嶋H上還需要提供Extension之外的某些功能。OS X沒(méi)有這樣的要求辙纬,其上的包含應(yīng)用程序不需要提供任何額外的功能豁遭。
雖然說(shuō)必須有一個(gè)「容器軟件」來(lái)包含各種擴(kuò)展應(yīng)用,擴(kuò)展應(yīng)用和容器軟件仍舊分開(kāi)運(yùn)行贺拣。每個(gè)擴(kuò)展都是一個(gè)以「.appex」作為擴(kuò)展名的二進(jìn)制文件蓖谢。該種類型的文件可以被打開(kāi)、完成給定任務(wù)譬涡、而后在容器軟件未被關(guān)閉的情況下關(guān)閉擴(kuò)展闪幽。同時(shí)我們也可以預(yù)想到,許多的應(yīng)用軟件內(nèi)有著同樣的擴(kuò)展涡匀。比如說(shuō)盯腌,Instagram 的擴(kuò)展是可以給圖像添加濾鏡。很多其他的圖像處理軟件也需要給圖像添加濾鏡陨瘩。此時(shí)蘋果公司鼓勵(lì)開(kāi)發(fā)者使用「嵌入框架」(embedded framework)共享他們完成此任務(wù)的代碼腕够。創(chuàng)建嵌入框架的步驟很簡(jiǎn)單,僅需創(chuàng)建一個(gè)框架舌劳、把代碼放進(jìn)框架內(nèi)帚湘、而后將框架嵌入容器軟件和應(yīng)用擴(kuò)展即可。唯一需要注意的地方是這種特性必須在 iOS 8.0 或者后續(xù)的系統(tǒng)中才能存在甚淡。之前版本的操作系統(tǒng)不支持此種類型的操作大诸。
蘋果公司嚴(yán)格的強(qiáng)制回收內(nèi)存機(jī)制是導(dǎo)致需要擴(kuò)展和容器應(yīng)用分開(kāi)運(yùn)行的重要原因之一。由于用戶經(jīng)常同時(shí)開(kāi)啟多個(gè)小插件贯卦,因此小插件的內(nèi)存管理受到的限制尤其嚴(yán)格资柔。這從 iPhone 4s 或者 iPad 2 這樣的設(shè)備上這些內(nèi)存受限的小插件的運(yùn)行機(jī)制就能看出。
文檔提到撵割,Extension的生命周期與它的包含應(yīng)用程序完全沒(méi)有關(guān)系贿堰,它由4個(gè)階段組成:
- 用戶選擇一個(gè)App Extension
- 系統(tǒng)啟動(dòng)它
- App Extension運(yùn)行
-
系統(tǒng)終止App Extension
如果兩個(gè)應(yīng)用程序需要同樣的Extension做相同的工作,那么這會(huì)發(fā)生在兩個(gè)獨(dú)立的Extension進(jìn)程中睁枕。
這一方法的主要?jiǎng)訖C(jī)是官边,通過(guò)生命周期短暫的Extension減少內(nèi)存使用和能量消耗沸手,并防止一個(gè)Extension的錯(cuò)誤影響到使用了相同Extension的應(yīng)用程序外遇。
Extension的類型
Extension有多種類型,每一種類型都綁定到一個(gè)稱為“擴(kuò)展點(diǎn)(Extension point)”的系統(tǒng)區(qū)域:
Extension point | Typical app extension functionality |
---|---|
Today (iOS and OS X) | Get a quick update or perform a quick task in the Today view of Notification Center(A Today extension is called a widget) |
Share (iOS and OS X) | Post to a sharing website or share content with others |
Action (iOS and OS X; UI and non-UI variants) | Manipulate or view content originating in a host app |
Photo Editing (iOS) | Edit a photo or video within the Photos app |
Finder Sync (OS X) | Present information about file sync state directly in Finder. |
Document Provider (iOS; UI and non-UI variants) | Provide access to and manage a repository of files. |
Custom Keyboard (iOS) | Replace the iOS system keyboard with a custom keyboard for use in all apps |
Watch App (iOS) | Provide an app, a glance, or a notification UI for Apple Watch, as described in App Programming Guide for watchOS. |
- “今日(Today契吉,又稱為Widget)”:可以快速獲取更新或者在通知中心的今日視圖中執(zhí)行一項(xiàng)快速任務(wù)跳仿。
- 共享:發(fā)布到一個(gè)共享網(wǎng)站或者與其它應(yīng)用程序共享內(nèi)容。
- 動(dòng)作:在另一個(gè)應(yīng)用程序的上下文中操作或查看內(nèi)容捐晶。
- 照片編輯(僅限于iOS):在照片應(yīng)用程序中編輯照片或視頻菲语。
- 查找器(僅限于OS X):在查找器中直接顯示文件同步的狀態(tài)信息妄辩。
- 文檔提供程序(僅限于iOS):提供對(duì)文件庫(kù)的訪問(wèn)和管理。
- 自定義鍵盤(僅限于iOS):用自定義鍵盤替代iOS系統(tǒng)鍵盤山上,并用于所有的應(yīng)用程序中眼耀。
- Watch App(僅限于iOS):為Apple Watch提供一個(gè)app,一個(gè)glance頁(yè)面或者一個(gè)通知UI佩憾,詳見(jiàn): App Programming Guide for watchOS哮伟。
由于每個(gè)擴(kuò)展點(diǎn)都有與之相關(guān)的使用策略和專門的API,開(kāi)發(fā)人員必須為他們想要提供的那種功能選擇恰當(dāng)?shù)臄U(kuò)展點(diǎn)妄帘。例如楞黄,在默認(rèn)情況下,鍵盤Extension“不能訪問(wèn)網(wǎng)絡(luò)抡驼,而且不能與其包含應(yīng)用程序共享同一容器”鬼廓。通過(guò)對(duì)Extension進(jìn)行恰當(dāng)?shù)呐渲茫@樣的限制可以移除致盟,但開(kāi)發(fā)人員仍然需要遵守蘋果應(yīng)用商店審查指南和iOS開(kāi)發(fā)者計(jì)劃許可協(xié)議中的具體的網(wǎng)絡(luò)鍵盤指南碎税。
Extension運(yùn)行機(jī)制
即使是iOS 8 允許運(yùn)行擴(kuò)展,卻仍舊在應(yīng)用勾邦、應(yīng)用擴(kuò)展以及應(yīng)用數(shù)據(jù)之間設(shè)置了許多的障礙蚣录。而這一切正是出于保護(hù)用戶以及用戶隱私的目的。實(shí)際上應(yīng)用之間仍舊不能直接交流眷篇。像之前提到的一樣萎河,應(yīng)用擴(kuò)展是小的二進(jìn)制文件,并且和容器應(yīng)用程序分開(kāi)來(lái)運(yùn)行蕉饼。調(diào)用這些擴(kuò)展的應(yīng)用程序(蘋果稱之為「主應(yīng)用」虐杯,host app)在調(diào)用并啟動(dòng)擴(kuò)展之后會(huì)與擴(kuò)展進(jìn)行直接的交流,然而主應(yīng)用與容器應(yīng)用之間永遠(yuǎn)不會(huì)建立連接昧港。即使主應(yīng)用想要調(diào)用一個(gè)擴(kuò)展擎椰,也是通過(guò)向蘋果的系統(tǒng)框架發(fā)送請(qǐng)求。此時(shí)僅僅啟動(dòng)應(yīng)用擴(kuò)展创肥,而不直接啟動(dòng)容器應(yīng)用达舒。
應(yīng)用擴(kuò)展和「主應(yīng)用」之間可以交流,然而此時(shí)擴(kuò)展和其容器應(yīng)用之間并不會(huì)直接建立聯(lián)系叹侄。
在 FortyTwo 公司的 iOS 開(kāi)發(fā)者 Eduardo Fonseca 向我們解釋了 iOS 是如何實(shí)現(xiàn)讓應(yīng)用和擴(kuò)展之間不建立聯(lián)系的效果的巩搏。
「每一個(gè)擴(kuò)展是在主應(yīng)用程序之內(nèi)的獨(dú)立的程序。這些擴(kuò)展擁有獨(dú)立的可執(zhí)行代碼趾代」岬祝」Fonseca 說(shuō),「然而有趣的是實(shí)際上擴(kuò)展并不是應(yīng)用程序撒强。蘋果的系統(tǒng)框架會(huì)通過(guò)已經(jīng)事先定義好的接口調(diào)用這些擴(kuò)展禽捆。擴(kuò)展的代碼會(huì)被分開(kāi)來(lái)單獨(dú)執(zhí)行笙什,也就是說(shuō)第三方應(yīng)用的『應(yīng)用空間』內(nèi)什么都不會(huì)執(zhí)行。這樣的話支持使用擴(kuò)展的應(yīng)用(比如 Safari)就不會(huì)有任何危險(xiǎn)胚想。同樣琐凭,在其他應(yīng)用內(nèi)執(zhí)行你的擴(kuò)展也不會(huì)遇到任何問(wèn)題。它們就像油和水一樣浊服,是完全不會(huì)融合的分開(kāi)的兩個(gè)部分淘正。」
即使應(yīng)用程序擴(kuò)展與其容器應(yīng)用之間必須有所交流臼闻,他們也必須通過(guò)系統(tǒng)接口非直接地進(jìn)行交流鸿吆。默認(rèn)下容器應(yīng)用與其應(yīng)用程序擴(kuò)展之間是不可以互相接觸到對(duì)方的數(shù)據(jù)的。
擴(kuò)展和其容器應(yīng)用必須通過(guò)接口和其他用來(lái)分享數(shù)據(jù)的特殊容器進(jìn)行非直接的交流
為了在容器應(yīng)用和其應(yīng)用擴(kuò)展之間分享數(shù)據(jù)述呐,你也許需要把容器應(yīng)用和擴(kuò)展都設(shè)置成一個(gè)「應(yīng)用群」(App Group) 的一部分惩淳。這樣就可以通過(guò)包含應(yīng)用沙箱和擴(kuò)展沙箱的一個(gè)第三方容器傳輸二者之間的數(shù)據(jù)。你可能想過(guò)為什么在 iOS 上登錄 Chrome 瀏覽器會(huì)讓你同時(shí)登錄谷歌地圖或者谷歌云端硬盤乓搬。這就是因?yàn)?Chrome思犁、谷歌地圖和谷歌云端硬盤都是谷歌的應(yīng)用群的一部分。然而即使在應(yīng)用群里进肯,數(shù)據(jù)的分享也有一些限制激蹲。它們之間能夠分享數(shù)據(jù)庫(kù)、緩存信息江掩、登錄信息等等学辱,但是本地存儲(chǔ)的媒體文件或者其他文件卻絕對(duì)不能分享。
把容器應(yīng)用和應(yīng)用擴(kuò)展放到一個(gè)應(yīng)用群里能夠使它們?cè)诜窒韰^(qū)域分享一些數(shù)據(jù)环形。否則容器應(yīng)用和應(yīng)用擴(kuò)展的數(shù)據(jù)會(huì)被存儲(chǔ)在不同的地方策泣。
簡(jiǎn)單地來(lái)總結(jié)一下上述內(nèi)容:蘋果公司不想讓一個(gè)應(yīng)用能夠進(jìn)入另一個(gè)應(yīng)用的沙箱內(nèi)。而應(yīng)用擴(kuò)展就像是在沙箱里的小沙箱抬吟,因此在主應(yīng)用調(diào)用擴(kuò)展時(shí)萨咕,擴(kuò)展不會(huì)將容器應(yīng)用內(nèi)的數(shù)據(jù)泄露給主應(yīng)用。
應(yīng)用程序擴(kuò)展的執(zhí)行方式和應(yīng)用程序的執(zhí)行方式也不一樣火本。如果你在不同的應(yīng)用內(nèi)同時(shí)開(kāi)起了多個(gè)同樣的應(yīng)用程序擴(kuò)展危队,系統(tǒng)實(shí)際上會(huì)打開(kāi)多個(gè)應(yīng)用程序擴(kuò)展進(jìn)程、每個(gè)都作為一個(gè)獨(dú)立的進(jìn)程單獨(dú)運(yùn)行钙畔。比如說(shuō)你在 Safari 里打開(kāi)了一個(gè)擴(kuò)展茫陆、而后在郵件里也打開(kāi)了一個(gè)同樣的擴(kuò)展,那么即使擴(kuò)展都一樣刃鳄,系統(tǒng)實(shí)際上會(huì)運(yùn)行兩個(gè)不同擴(kuò)展程序進(jìn)程盅弛。這些進(jìn)程之間不會(huì)利用你相同的存儲(chǔ)地址區(qū)域钱骂,因此這能讓兩個(gè)主應(yīng)用使用獨(dú)立的數(shù)據(jù)叔锐,并且如果一個(gè)應(yīng)用擴(kuò)展進(jìn)程崩潰了也不會(huì)影響另一個(gè)進(jìn)程挪鹏。像 Chrome 和 Safari 這樣的瀏覽器也出于同樣的目的,每個(gè)網(wǎng)頁(yè)標(biāo)簽實(shí)際上也是分別運(yùn)行的愉烙。
Extension限制
上線限制
像所有未越獄的 iPhone 里的軟件一樣讨盒,所有的 iOS 擴(kuò)展將需要從蘋果應(yīng)用商城中下載。不過(guò)此處最大的限制是蘋果公司不會(huì)允許開(kāi)發(fā)者提供僅僅作為擴(kuò)展出現(xiàn)的應(yīng)用步责。開(kāi)發(fā)者必須提供一個(gè)基本的「容器應(yīng)用程序」返顺,擴(kuò)展則作為錦上添花的內(nèi)容存在于這個(gè)基本的應(yīng)用程序內(nèi)。蘋果公司強(qiáng)調(diào)蔓肯,這個(gè)基本的「容器應(yīng)用」必須提供給用戶一些基本的功能遂鹊,否則他們不會(huì)授權(quán)該軟件登陸應(yīng)用商店。這一點(diǎn)有別于安卓蔗包。
通信限制
對(duì)于Extension與其它應(yīng)用程序之間的通信秉扑,蘋果有幾項(xiàng)強(qiáng)制規(guī)定:
1. 調(diào)用Extension的應(yīng)用程序即主應(yīng)用程序不能啟動(dòng)Extension;只有系統(tǒng)可以啟動(dòng)Extension调限。
2. 當(dāng)Extension啟動(dòng)后舟陆,主應(yīng)用程序就和它直接通信。
3. 主應(yīng)用程序永遠(yuǎn)不和包含應(yīng)用程序直接通信耻矮。
4. Extension不是一個(gè)應(yīng)用程序秦躯,但它由系統(tǒng)生成,并有它自己?jiǎn)为?dú)的進(jìn)程裆装。
5. 為了在包含應(yīng)用程序和它的Extension之間共享數(shù)據(jù)踱承,包含應(yīng)用程序及其Extension都必須是應(yīng)用程序組的一部分。對(duì)于應(yīng)用程序組的其中兩個(gè)成員哨免,部分?jǐn)?shù)據(jù)可以在兩者沙箱之外的第三個(gè)容器中共享勾扭。
正如Ars Technica的Andrew Cunningham總結(jié)的那樣,這些
規(guī)則的最終結(jié)果主要是一個(gè)應(yīng)用程序不能進(jìn)入另一個(gè)應(yīng)用程序的沙箱铁瞒。這與Android相反妙色,在Android上,內(nèi)容提供程序和解析程序仍然可以一起工作來(lái)為應(yīng)用程序提供對(duì)其它應(yīng)用程序中數(shù)據(jù)的訪問(wèn)慧耍。
參考鏈接:
App Extension Programming Guide
App Extension編程指南(iOS8/OS X v10.10):創(chuàng)建應(yīng)用擴(kuò)展
WWDC2014 IOS8 APP Extensions
App Extension編程指南(iOS8/OS X v10.10):擴(kuò)展類型--自定義鍵盤
如何在Swift中創(chuàng)建Action擴(kuò)展