Application Extension 是從 iOS 8 開始出現的一種使用者互動介面
Extension 顧名思義就是擴展的意思,而 Application Extension 就是 App 的擴展
所以說 Application Extension 本身並不是單獨一個 App,而是需要仰賴 App 才能運作的
而 Application Extension 本身的 LifeCycle (生命週期) 也跟一般 App 不同
有些是需要使用者手動啟動,有些則是可以在各個 App 中被啟動
像是鍵盤輸入法 (Custom Keyboard Extension)、密碼自動填入 (AutoFill Credential Provider) 等就是需要使用者手動去啟動
而 Share Extension、Action Extension 這兩個則是可以在各個 App 中被啟動
前面有說到 Application Extension 的 LifeCycle 跟一般 App 是不一樣的
讓我們來看一下 Application Extension 是怎麼運作的
▲ 圖取自 Apple Developer Documentation
開頭有說到 Application Extension 是需要依賴 App 本體才能運作
既然是這樣,那麼 Application Extension 跟 App 也是可以相互溝通的
讓我們來看一下 Application Extension 跟 App 之間是怎麼相互溝通
▲ 圖取自 Apple Developer Documentation
▲ 圖取自 Apple Developer Documentation
Containing App:App 本體
App Extension:Containing App 的擴展,需依賴於 Containing App
Host App:呼叫 App Extension 的 App
在簡單版中,可以看到 Host App 呼叫的是 App Extension 而不是 Containing App
App Extension 與 Host App兩者之間可以進行 Request 跟 Response 溝通
而 App Extension 與 Containing App 之間以虛線標示是因為
App Extension 執行的時候 Containing App 是可以不用執行的
也就是 App Extension 與 Containing App 之間是可以不用有溝通的
接著,我們來看進階版,App Extension 與 Host App 之間的溝通一樣
但與 Containing App 之間卻不一樣了,兩者之間多了 Open URL
、Shared resources
互動
首先是 Open URL,這個是只有 Widget Extension 才能使用
透過下面這個 Function 來實作,用於點擊 Widget 後,跳回 Containing App
func open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil)
Containing App 與 App Extension 之間有時候會需要有資料共用、傳輸的需求
那一般來說是做不到的,主要是因為 iOS 系統讓 App、App Extension 都是透過 Sandbox (沙盒) 運作的,所以兩者之間是八竿子打不著的
我們可以透過下面這個例子,來知道如果 App 中有使用 SQLite 的話,會在兩邊都建立一個 db 檔
# Containing App 建立的 db 檔
/var/mobile/Containers/Data/Application/E5E6E516-0163-4754-9D10-A5F6C33A6261/Documents/app.db
# App Extension 建立的 db 檔
/var/mobile/Containers/Data/PluginKitPlugin/0A99BB23-E261-4AB9-8DA1-29EFA6E2649E/Documents/app.db
從上面路徑可以看到從「/var/mobile/Containers/Data/」後面兩者的路徑就不一樣了
Containing App 是建立在「Application/」下,而 App Extension 是建立在「PluginKitPlugin/」
難怪會在 Containing App 跟 App Extension 兩邊都各建立一個 db 檔
那該怎麼處理呢?
我們可以透過 App Groups 來讓 Containing App 跟 App Extension 共同讀寫同一個區域
這裡就稍微說一下,App Groups 要如何開啟 (Containing App 跟 Extension 開啟方法都一樣)
Containing App 跟 App Extension 兩邊都要開啟 App Groups 才行喔!
0. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> Signing 選 Apple 付費開發者帳號
1. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> App Groups
2. App Groups -> + -> 輸入 group.<你想取的名稱>
接著有兩個方式可以讓 Containing App 跟 App Extension 共同存取資料
UserDefaults(suiteName: "group.<你想取的名稱>")
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.<你想取的名稱>")
從 Apple Developer Documentation 中可以知道
有些事情是不能在 Application Extension 做的,如下圖
▲ 圖取自 Apple Developer Documentation
不負責翻譯如下
Application Extension 幫 App 新增許多可玩性
在下一篇會以 AutoFill Credential Provider 來當作範例實作 App Extension