WWDC2014之App Extensions學習筆記
阿新 • • 發佈:2019-02-16
一、關於App Extensions
extension是iOS8新開放的一種對幾個固定系統區域的擴充套件機制,它可以在一定程度上彌補iOS的沙盒機制對應用間通訊的限制。
extension的出現,為使用者提供了在其它應用中使用我們應用提供的服務的便捷方式,比如使用者可以在Today的widgets中檢視應用展示的簡略資訊,而不用再進到我們的應用中,這將是一種全新的使用者體驗;但是,extension的出現可能會減少使用者啟動應用的次數,同時還會增大開發者的工作量。
幾個關鍵詞
extension point
系統中支援extension的區域,extension的類別也是據此區分的,iOS上共有Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard幾種,其中Today中的extension又被稱為widget。
每種extension point的使用方式和適合乾的活都不一樣,因此不存在通用的extension。
app extension
即為本文所說的extension。extension並不是一個獨立的app,它有一個包含在app bundle中的獨立bundle,extension的bundle字尾名是.appex。其生命週期也和普通app不同,這些後文將會詳述。
extension不能單獨存在,必須有一個包含它的containing app。
另外,extension需要使用者手動啟用,不同的extension啟用方式也不同,比如: 比如Today中的widget需要在Today中啟用和關閉;Custom keyboard需要在設定中進行相關設定;Photo Editing需要在使用照片時在照片管理器中啟用或關閉;Storage Provider可以在選擇檔案時出現;Share和Action可以在任何應用裡被啟用,但前提是開發者需要設定Activation Rules,以確定extension需要在合適出現。
containing app
儘管蘋果開放了extension,但是在iOS中extension並不能單獨存在,要想提交到AppStore,必須將extension包含在一個app中提交,並且app的實現部分不能為空,這個包含extension的app就叫containing app。
extension會隨著containing app的安裝而安裝,同時隨著containing app的解除安裝而解除安裝。
host app
能夠調起extension的app被稱為host app,比如widget的host app就是Today。
二、extension和containing app、host app
2.1 extension和host app
extension和host app之間可以通過extensionContext屬性直接通訊,該屬性是新增加的UIViewController類別:
- @interface UIViewController(NSExtensionAdditions) <NSExtensionRequestHandling>
- // Returns the extension context. Also acts as a convenience method for a view controller to check if it participating in an extension request.
- @property (nonatomic,readonly,retain) NSExtensionContext *extensionContext NS_AVAILABLE_IOS(8_0);
- @end
- //通過openURL的方式啟動Containing APP
- - (void)openURLContainingAPP
- {
- [self.extensionContext openURL:[NSURL URLWithString:@"appextension://123"]
- completionHandler:^(BOOL success) {
- NSLog(@"open url result:%d",success);
- }];
- }
- //讓隱藏的外掛重新顯示
- - (void)showTodayExtension
- {
- [[NCWidgetController widgetController] setHasContent:YES forWidgetWithBundleIdentifier:@"com.wangzz.app.extension"];
- }
- //隱藏外掛
- - (void)hiddeTodayExtension
- {
- [[NCWidgetController widgetController] setHasContent:NO forWidgetWithBundleIdentifier:@"com.wangzz.app.extension"];
- }
- TARGETS-->AppExtensionDemo-->Capabilities-->App Groups
- TARGETS-->TodayExtension-->Capabilities-->App Groups
- - (void)saveTextByNSUserDefaults
- {
- NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];
- [shared setObject:_textField.text forKey:@"wangzz"];
- [shared synchronize];
- }
- - (NSString *)readDataFromNSUserDefaults
- {
- NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];
- NSString *value = [shared valueForKey:@"wangzz"];
- return value;
- }
- - (BOOL)saveTextByNSFileManager
- {
- NSError *err = nil;
- NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
- containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];
- NSString *value = _textField.text;
- BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
- if (!result) {
- NSLog(@"%@",err);
- } else {
- NSLog(@"save value:%@ success.",value);
- }
- return result;
- }
- - (NSString *)readTextByNSFileManager
- {
- NSError *err = nil;
- NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
- containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];
- NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&err];
- return value;
- }
- - (BOOL)copyFrameworkFromMainBundleToAppGroup
- {
- NSFileManager *manager = [NSFileManager defaultManager];
- NSError *err = nil;
- NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
- NSString *sorPath = [NSString stringWithFormat:@"%@/Dylib.framework",[[NSBundle mainBundle] bundlePath]];
- NSString *desPath = [NSString stringWithFormat:@"%@/Library/Caches/Dylib.framework",containerURL.path];
- BOOL removeResult = [manager removeItemAtPath:desPath error:&err];
- if (!removeResult) {
- NSLog(@"%@",err);
- } else {
- NSLog(@"remove success.");
- }
- BOOL copyResult = [[NSFileManager defaultManager] copyItemAtPath:sorPath toPath:desPath error:&err];
- if (!copyResult) {
- NSLog(@"%@",err);
- } else {
- NSLog(@"copy success.");
- }
- return copyResult;
- }
- - (BOOL)loadFrameworkInAppGroup
- {
- NSError *err = nil;
- NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
- NSString *desPath = [NSString stringWithFormat:@"%@/Library/Caches/Dylib.framework",containerURL.path];
- NSBundle *bundle = [NSBundle bundleWithPath:desPath];
- BOOL result = [bundle loadAndReturnError:&err];
- if (result) {
- Class root = NSClassFromString(@"Person");
- if (root) {
- Person *person = [[root alloc] init];
- if (person) {
- [person run];
- }
- }
- } else {
- NSLog(@"%@",err);
- }
- return result;
- }
- - (void)logAppPath
- {
- //app group路徑
- NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
- NSLog(@"app group:\n%@",containerURL.path);
- //列印可執行檔案路徑
- NSLog(@"bundle:\n%@",[[NSBundle mainBundle] bundlePath]);
- //列印documents
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *path = [paths objectAtIndex:0];
- NSLog(@"documents:\n%@",path);
- }
- 2014-06-23 19:35:03.944 AppExtensionDemo[7471:365131] app group:
- /private/var/mobile/Containers/Shared/AppGroup/89CCBFB1-CA5E-4C7F-80CB-A3EB9E841816
- 2014-06-23 19:35:03.946 AppExtensionDemo[7471:365131] bundle:
- /private/var/mobile/Containers/Bundle/Application/1AC73797-A3BB-4BDE-A647-3D083DA6871A/AppExtensionDemo.app
- 2014-06-23 19:35:03.948 AppExtensionDemo[7471:365131] documents:
- /var/mobile/Containers/Data/Application/E5E6E516-0163-4754-9D10-A5F6C33A6261/Documents
- Jun 23 19:37:49 autonavis-iPad com.foogry.AppExtensionDemo.TodayExtension[7638] <Warning>: app group:
- /private/var/mobile/Containers/Shared/AppGroup/89CCBFB1-CA5E-4C7F-80CB-A3EB9E841816
- Jun 23 19:37:49 autonavis-iPad com.foogry.AppExtensionDemo.TodayExtension[7638] <Warning>: bundle:
- /private/var/mobile/Containers/Bundle/Application/596717B7-7CB8-4F53-BCD4-380F34ABD30F/AppExtensionDemo.app/PlugIns/com.foogry.AppExtensionDemo.TodayExtension.appex
- Jun 23 19:37:49 autonavis-iPad com.foogry.AppExtensionDemo.TodayExtension[7638] <Warning>: documents:
- /var/mobile/Containers/Data/PluginKitPlugin/57581433-3DBD-4930-971F-78D30C150E8A/Documents