App Extension
App Extension是從iOS8開始引入的一種應用服務和交互方式。App Extension需要依賴于容器應用(Containing App)發布和部署。常見的App Extension例如:Today Extension 和 Share Extension等。
-
容器應用(Containing App) 和 宿主應用(Host App):
- 容器應用(Containing App):即由開發者開發的主應用。
- 宿主應用(Host App):能夠運行Extension的應用即為宿主應用,Today Extension對應的宿主應用即為Today View。Share Extension對應的宿主應用即為能夠調起Share Extension的第三方應用。
App Extension、Host App、Containing App 三者之間的關系:
- App Extension的基本生命周期:
- App Extension基本認知:
- Extension不能單獨發布和部署,需要依賴于容器應用(Containing App)。
- Extension和容器應用(Containing App)的生命周期是獨立的,分別為兩個不同的進程.
- Extemsion的運行依賴于宿主應用(Host App),生命周期由宿主應用決定。
- Extension作為一個單獨的target存在,但會隨著容器應用(Containing App)的安裝和卸載而安裝和卸載。
- Extension需要獨立的證書用來打包和測試。
widgets簡介
-
widgets介紹:
- 在iOS系統中有多種Extension,Today Extension作為其中之一,通常被稱為widgets。widgets讓用戶在鎖屏狀態下(鎖屏狀態下直接調起Containing App 需要解鎖后才能調起)和解鎖狀態下,都可以通過widgets來瀏覽應用當前的重要信息。
- 注:iOS和OS X系統都支持widgets,下文僅以iOS系統中的widgets展開說明。
-
widgets的正確使用姿勢:
適當響應用戶交互。
展示最新的Containing App內容。
正確的使用widgets并盡可能減少其內存占用,否則系統會終止widgets。
注:根據官方推薦的widgets使用方式,widgets中不應該出現復雜的交互或者做耗時的操作。
-
widgets中對UI的約束:
widgets中不支持滑動類型的交互設計。
widgets中不支持鍵盤,所以不應出現輸入框類設計。
注:widgets視圖寬度是由today view來決定的,高度局部可調。以4.7屏幕為例,高度最大不要超過528,最小為110,寬度為359。
-
widgets生命周期:
- 第一次下拉Today View的時候widgets的生命周期即為viewController的生命周期,但是再次下拉Today View的時候由于系統采用快照的方式填充widgets,直到其內容更新或者UI被更新才被替換,所以再次下拉的時候起生命周期只會執行viewWillAppear方法。
創建widgets
- 打開Containing App的項目(即需要添加Today Extension的App),添加Extension的target。
- 選擇Today Extension。
- 添加Extension后的target。
- 系統提供的默認入口為MainInterface.storyboard文件。
- 如果使用代碼的方式自定義controller,需要更改info.plist中NSExtensionMainStoryboard字段為NSExtensionPrincipalClass,并修改入口為自定義類。
到這里Today Extension即widget已經可以運行并顯示了。
- 設置 App Extentsion 顯示名:
- 設置extension target的info.plist.
- iOS8-iOS9中Widget的AppIcon需要設置才能正確顯
- 可以在Extension Target中單獨創建Assets,然后添加AppIcon,也可以直接設置Containing App 中的Assets為 兩個Target共用。
- Extension Target -> Build Settings -> Assset Catalog Compiler - Options -> Asset Catalog App Icon Set Name 添加AppIcon名字即可。
-
widgets的更新機制說明:
- 為了保證當前內容為最新的內容,系統偶爾會捕獲widgets的視圖快照,當widgets再次可見時,將顯示最新的快照,直到更新的實時版本替換為止。
-
widgets更新內容
- 如果想要在系統捕獲快照前更新widgets的內容,就要遵守NCWidgetProviding協議。并在方法
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult result))completionHandler;
中做內容更新操作。
- widgets 的隱藏和顯示
- 在沒有內容或者沒有最新內容的情況下可以選擇隱藏widgets,系統指定了一種用來隱藏和顯示widgets的方式:
/**
* flag: BOOL 隱藏或者顯示
* bundleID: 要隱藏或者顯示的Extension的bundleId
*/
- (void)setHasContent:(BOOL)flag forWidgetWithBundleIdentifier:(NSString *)bundleID;
該方法在App Extension和Containing App中都可以調用,需要導入#import <NotificationCenter/NotificationCenter.h>
-
App Extension 和 Containing App 的通信:
- App Extension 和 Containing App 的通信需要分別對App Extension 和 Containing App 都開啟App Groups,二者使用相同的group。
-
App Extension 調起 Containing App:
- 通過自定義URL scheme的方式調起Containing App,系統提供了NSExtensionContext來實現這種方式。
[self.extensionContext openURL:[NSURL URLWithString:@"yourContainingAppCustomURLScheme://?parma=value"] completionHandler:^(BOOL success) { NSLog(@"%u", success); }];
- 自定義URL Scheme的方式在調起Containing App的同時也可以進行數據傳遞。
-
通過group的方式實現App Extension 和 Containing App的數據共享
- group的方式會為App Extension 和 Containing App 創建一個二者都可以訪問的沙盒路徑,所有需要共享的數據都存放在group路徑中。這個路徑以groupid為標識唯一存在。
- 獲取group路徑:
NSString *suiteName = @"group.com.iticle.TodayExtensionDemo"; NSString *groupPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:suiteName]
* NSUserDefault * 創建一個group路徑下的userDefault: ```-objc NSString *suiteName = @"group.com.iticle.TodayExtensionDemo"; _userDefalut = [[NSUserDefaults alloc] initWithSuiteName:suiteName]; ``` * NSFileManager(推薦NSFileCoordination避免讀寫同步的問題) * Sqlite/CoreData
- group的方式會為App Extension 和 Containing App 創建一個二者都可以訪問的沙盒路徑,所有需要共享的數據都存放在group路徑中。這個路徑以groupid為標識唯一存在。
-
App Extension 和 Containing App 代碼共享:
- 共享自定義代碼
- framework
- 給需要共享的代碼添加一個target
- 共享Cocoapods引入的第三方庫
-
修改podfile文件,添加App Extension的target依賴的第三方庫
img_4.png
-
- 共享自定義代碼
文章鏈接
https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Today.html
https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionCreation.html#//apple_ref/doc/uid/TP40014214-CH5-SW8
https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html#//apple_ref/doc/uid/TP40014214-CH2-SW2
https://developer.apple.com/documentation/notificationcenter