###### tags: `第14屆IT邦鐵人賽文章` # 【在 iOS 開發路上的大小事2-Day17】Application Extension 簡介 ![](https://i.imgur.com/QswfhmY.png) ## 前情提要 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 中被啟動 ## LifeCycle 生命週期 前面有說到 Application Extension 的 LifeCycle 跟一般 App 是不一樣的 讓我們來看一下 Application Extension 是怎麼運作的 ![](https://i.imgur.com/Ef8qEHS.png) ▲ 圖取自 [Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html) 1. 使用者啟動 Application Extension 2. 系統啟動 Application Extension 3. 執行 Application Extension 內的程式 4. 系統關閉 Application Extension ## 與 App 之間的溝通 開頭有說到 Application Extension 是需要依賴 App 本體才能運作 既然是這樣,那麼 Application Extension 跟 App 也是可以相互溝通的 讓我們來看一下 Application Extension 跟 App 之間是怎麼相互溝通 ### 簡單版 ![](https://i.imgur.com/4YPp7da.png) ▲ 圖取自 [Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html) ### 進階版 ![](https://i.imgur.com/quuKL0F.png) ▲ 圖取自 [Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html) ### 名詞解說 ``` 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 首先是 Open URL,這個是只有 Widget Extension 才能使用 透過下面這個 Function 來實作,用於點擊 Widget 後,跳回 Containing App ```swift func open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil) ``` #### Shared resources 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 這裡就稍微說一下,App Groups 要如何開啟 (Containing App 跟 Extension 開啟方法都一樣) Containing App 跟 App Extension 兩邊都要開啟 App Groups 才行喔! ![](https://i.imgur.com/NPvsjue.png) ``` 0. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> Signing 選 Apple 付費開發者帳號 1. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> App Groups 2. App Groups -> + -> 輸入 group.<你想取的名稱> ``` 接著有兩個方式可以讓 Containing App 跟 App Extension 共同存取資料 1. UserDefaults 2. FileManager #### UserDefaults ```swift UserDefaults(suiteName: "group.<你想取的名稱>") ``` #### FileManager ```swift FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.<你想取的名稱>") ``` ## 不能在 Application Extension 做的事情 從 Apple Developer Documentation 中可以知道 有些事情是不能在 Application Extension 做的,如下圖 ![](https://i.imgur.com/jf74COB.png) ▲ 圖取自 [Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html) 不負責翻譯如下 1. 不能存取 sharedApplication 物件,所以不能使用 sharedApplication 物件中的任何 Methods 2. 不能使用任何被標記 NS_EXTENSION_UNAVAILABLE 的 API 或類似的標記, 以及 unavailable Framework 中的任何 API,像是 HealthKit、EventKit UI Framework 3. 不能在 iOS 裝置上使用相機與麥克風 (iMessage App 可以,只需要在 Info.plist 中新增 NSCameraUsageDescription、NSMicrophoneUsageDescription) 4. 執行長時間的背景任務 5. 透過 AirDrop 來接收資料 ## 總結 Application Extension 幫 App 新增許多可玩性 在下一篇會以 AutoFill Credential Provider 來當作範例實作 App Extension