iOS開發 之 App Extension 整體總結

來源:互聯網
上載者:User

標籤:方法   選項   body   觸控螢幕   container   init   介面   key   pps   

 

一、App Extension的介紹

   App Extension可以讓你擴充你APP的自訂功能和內容,使使用者可以在與其他應用或者系統進行互動的時候去使用它。app extension即為本文所說的extension。extension並不是一個獨立的app,它有一個包含在app bundle中的獨立bundle,extension的bundle尾碼名是.appex。其生命週期也和普通app不同,這些後文將會詳述。extension不能單獨存在,必須有一個包含它的containing app。擴充(app Extension )是 iOS 8 中引入的一個非常重要的新特性

  extension的啟用方式:不同的extension啟用方式也不同,有的extension需要使用者手動啟用而有的可以在任何應用裡被啟用,比如:Today中的widget需要在Today中啟用和關閉;Custom keyboard需要在設定中進行相關設定;Photo Editing需要在使用照片時在照片管理器中啟用或關閉;Storage Provider可以在選擇檔案時出現;Share和Action可以在任何應用裡被啟用,但前提是開發人員需要設定Activation Rules,以確定extension需要在合適出現。

  我們平時看到的Widget、和QQ的share等等,都是App Extension,是一些例子:

                                     

 

 

幾個關鍵詞  extension point系統中支援extension的地區叫做extension point(擴充點),extension的類別也是據此區分的,iOS上共有Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard幾種,其中Today中的extension又被稱為widget。每種extension point的使用方式和適合乾的活都不一樣,因此不存在通用的extension。  containing app containing app我們可以把它理解為容器App,就像的share extension,容器app就是。儘管蘋果開放了extension,但是在iOS中extension並不能單獨存在,要想提交到AppStore,必須將extension包含在一個app中提交,並且app的實現部分不可為空,這個包含extension的app就叫containing app。extension會隨著containing app的安裝而安裝,同時隨著containing app的卸載而卸載。  host app我們可以把它理解為宿主的App,能夠調起extension的app被稱為host app,比如:Safari app 裡面網頁分享到,  Safari就是 host app ; widget的host app就是Today。

 

 

二、 Extension的種類

 

我們可以在Xcode的File--->New--->Target裡面看到不同平台的Extension,包括iOS、watchOS、tvOS、macOS等等。這裡主要介紹iOS,主要包括以下幾種Extensions:

也可直接參考官方文檔 

iOS 8 系統有 6 個支援擴充的系統地區,分別是 Today 、 Share 、 Action 、 Photo Editing 、 Storage Provider 、 Custom keyboard 。支援擴充的系統地區也被稱為擴充點。

Today Widget

Today擴充 可以快速擷取更新或者在通知中樞的近日視圖中執行一項快速任務。對於賽事比分,股票、天氣、快遞這類需要即時擷取的資訊,可以在通知中樞的Today 視圖中建立一個 Today 擴充實現。 Today 擴充又稱為 Widget 。

Today擴充 

Share Extension

分享擴充,發布一個共用網站或者與其他應用共用內容,在 iOS 8 之前,使用者只有 Facebook,Twitter 等有限的幾個分享選項可以選擇。在 iOS 8 中,開發人員可以建立自訂的分享選項。

Share擴充

Action Extension

動作擴充,在另一個應用程式的上下文中操作或者查看內容, 在所有支援的擴充點中擴充性最強的一個。它可以實現轉換另一個 app 上下文中的內容。蘋果在 WWDC 大會上示範了一個 Bing 翻譯動作擴充,它可以將在 Safari 中選中的文本翻譯成不同的語言。

     Action擴充注意??: Host App(照片、Safari、郵件、語音等)分享菜單第一行是: Share Extension ;第二行是:  Action Extension;

Photo Editing

圖片編輯擴充,在照片app中編輯照片或者視頻,在 iOS 8 之前,如果你想為你的照片添加一個特殊的濾鏡,你需要進入第三方 app 中,這個過程是相當繁瑣的。在 iOS 8 中,你可以直接在 Photos 中使用第三方 app ,如 Instagram , VSCO cam 、 Aviary 提供的 Photo Editing 擴充完成對圖片的編輯,而無需離開當前的 app 。

 Photo Editing擴充

Document Provider

Document Provider 讓跨多個檔案儲存體服務之間的管理變得更簡單。類似 Dropbox 、 Google Drive 等儲存供應商通過在 iOS 8 中提供一個 Document Provider 擴充, app 直接可以使用這些擴充檢索和隱藏檔而不再需要建立不必要的拷貝。

 Document Provider擴充

Custom Keyboard

鍵盤擴充,例如第三方的鍵盤,搜狗IME,百度IME等。蘋果公司在 2007 年率先推出了觸控螢幕鍵盤,但一直沒多大改進。在這一方面, Android 則將鍵盤許可權開放給了第三方開發人員,所以出現了許多像 Swype , SwiftKey 等優秀的鍵盤IME。在 iOS 8 中,蘋果終於將鍵盤許可權開發給了第三方開發人員,自訂鍵盤IME可以讓使用者在整個系統範圍內使用。

 Custom Keyboard擴充 

以下是iOS 9和之後中新增擴充

1.Audio Unit Extension:音頻單元擴充

2.Broadcast UI Extension:廣播UI 擴充

3.Broadcast Upload Extension:廣播上傳擴充

4.Call Directory Extension:呼叫目錄擴充

5.Content Blocker Extension:內容攔截器擴充

6.iMessage Extension:訊息的擴充

7.Intents Extension:Intents擴充

8.Intents UI Extension:Intents UI擴充

9.Notification Content Extension:通知內容擴充

10.Notification Service Extension:通知服務擴充

11.Shared Links Extension:分享連結擴充功能

12.Spotlight Index Extension:Spotlight 索引擴充

13.Sticker Pack Extension:貼紙包擴充

 

三、App Extensions的生命週期

以下是蘋果官方提供的圖片:

 

 

1.使用者選擇要使用的App extension

2.系統啟動App Extension

3.App Extension 代碼運行

4.運行完之後系統kill掉App Extension

這就是App Extension的生命週期,舉個例子:

一個Share Extension,在圖庫裡面你選擇了一張圖片,然後點擊分享,選擇你的Share Extension(第一步),此時系統會啟動你的Share Extension(第二步)。然後你將選擇的圖片分享到指定的程式(例如的發送給朋友)(第三步)。接下來分享頁面關閉,系統kill掉了Share Extension。

 

四、App Extension的通訊方式

App Extension主要的通訊是和他的host app(例如的Share Extension和)

這個展示的就是正在啟動並執行App Extension、host app和containing app之間的關係。可以看出:Containing App和app Extension並沒有直接的溝通。甚至有的時候Containing app可以不運行,而App Extension直接運行。Containing app和Host app沒有任何的溝通。

在一個典型的request/response中,系統開啟代表host app(圖庫)的extension(分享的share extension),把host app提供的資料(圖片和選擇的好友)輸送到extension的context,然後extension展示介面,提供一些功能任務(例如的分享到朋友)。

 

還有一種是app extension可以直接和他的containing app溝通:

例如Today Widget,可以直接告訴系統開啟他的Containing app,只需要調用NSExtensionContext的openURL:CompletionHandler:方法即可。

app extension和containing app可以共同讀寫一個被稱為Shared resources的儲存地區,這是通過App Groups實現的。

 

這裡需要注意的是,在iOS 8.0中,只有Today Extension才支援直接調用NSExtensionContextopenURL:completionHandler:開啟URL連結;Share/Action Extension要想實現URL Scheme,只能建立一個Sink UIWebVew對URL進行loadRequest實現曲線救國(所謂“Sink”是指隱而不顯,例如frame=CGRectZero)現在這個方法也不行了(可見蘋果是不推薦開啟主app的)但是如果你不怕蘋果審核不通過 或者 下架 也可以用以下方法開啟:

 

//    UIWebView *webView = [[UIWebView alloc]init];//    webView.hidden = YES;//    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"weixin://"]];//    [webView loadRequest:request];//    [self.view addSubview:webView]; //這個方法已經打不開了        UIResponder* responder = self;    while ((responder = [responder nextResponder]) != nil) {        if ([responder respondsToSelector:@selector(openURL:)] == YES) {            [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:[NSString stringWithFormat:@"weixin://"]]];        }    }

 

stackoverflow 裡面有關於 Share Extension to open containing app 相關的解答 

 

五、App Groups 實現資料共用這是iOS8新開放的功能,在OS X上早就可用了。它主要用於同一group下的app共用同一份讀寫空間,以實現資料共用。extension和containing app共同讀寫一份資料是很合理的需求,比如系統的股市應用,widget和app中都需要展示幾個公司的股票資料,這就可以通過App Groups實現。  功能開啟 為了便於後續操作,請先確保你的開發人員帳號在Xcode上處於登入狀態。(或者在開發人員帳號中先建立好app group id )  一、在app中開啟App Groups位於:
  1. TARGETS-->AppExtensionDemo-->Capabilities-->App Groups 
找到以後,將App Groups右上方的開關開啟,然後選擇添加groups,比如我的是group.wangzz,當然這是為了測試隨便起得名字,正規點得命名規則應該是:group.com.company.app。 添加成功以後如所示:   二、在extension中也要開啟我建立的是widget,target名稱為TodayExtension,對應的App Groups位於:
  1. TARGETS-->TodayExtension-->Capabilities-->App Groups 
開啟方式和app中一樣,需要注意的是必須保證這裡地App Groups名稱和app中的相同,即為group.wangzz。 

三、extension和containing app資料共用

App Groups給我們提供了同一group內app可以共同讀寫的地區,可以通過以下方式實現資料共用:  3.1 通過NSUserDefaults共用資料 存資料通過以下方式向NSUserDefaults中儲存資料:
- (void)saveTextByNSUserDefaults {     NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];     [shared setObject:_textField.text forKey:@"wangzz"];     [shared synchronize]; } 

 

 

需要注意的是: 1.儲存資料的時候必須指明group id; 2.而且要注意NSUserDefaults能夠處理的資料只能是可plist化的對象,詳情見Property List Programming Guide。 3.為了防止出現資料同步問題,不要忘記調用[shared synchronize];  讀資料對應的讀取資料方式:
- (NSString *)readDataFromNSUserDefaults {     NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];     NSString *value = [shared valueForKey:@"wangzz"];  return value; } 

 

 

3.2 通過NSFileManager共用資料 NSFileManager在iOS7提供了containerURLForSecurityApplicationGroupIdentifier方法,可以用來實現app group共用資料。  儲存資料

 

- (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; } 

 

 

 在這裡我試著儲存和讀取的是字串資料,但讀寫SQlite我相信也是沒問題的。  資料同步兩個應用共同讀取同一份資料,就會引發資料同步問題。WWDC2014的視頻中建議使用NSFileCoordination實現普通檔案的讀寫同步,而資料庫可以使用CoreData,Sqlite也支援同步。  四、extension和containing app代碼共用 和資料共用類似,extension和containing app很自然地會有一些商務邏輯上可以共用的代碼,這時可以通過iOS8中剛開放使用的framework實現。蘋果在App Extension Programming Guide中是這樣描述的: In iOS 8.0 and later, you can use an embedded framework to share code between your extension and its containing app. For example, if you develop image-processing code that you want both your Photo Editing extension and its containing app to share, you can put the code into a framework and embed it in both targets. 即將framework分別嵌入到extension和containing app的target中實現代碼共用。(意思是:需要分別要將framework分別copy到extension和containing app的main bundle中。) 也就是說代碼是不可以共用的 要想用containing app的代碼只有 在copy 一份。  以下自己思考的作為參考:參考extension和containing app資料共用,我試想能不能將framework只儲存一份放在App Groups地區? 4.1 copy framework到App Groups 在app初次開機的時候將framework放到App Groups地區:
- (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; } 
  4.2 使用framework:
- (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; }      
經過測試,竟然能夠載入成功。 需要說明的是,這裡只是說那麼用是可以成功載入framework,但還面臨不少問題,比如如果使用者在啟動app之前去使用extension,這時framework還沒有copy過去,怎麼處理;另外iOS的機制或者蘋果的審核是否允許這樣使用等。 在一切確定下來之前還是乖乖按文檔中的方式使用吧。  六、在App Extension中不可以做的事情

一個app extension不能有以下情況:

1.訪問sharedApplication對象。因此不能使用任何該對象的防範

2.使用任何標記NS_EXTENSION_UNAVAILABLE宏的API,或者類似的宏,或者不可用framework裡面的API,例如HealthKit framework不能用於app extensions

3.iOS裝置訪問相機或者麥克風(iMessage app可以訪問這些資源,只要在Info.plist裡面進行配置使用描述即可)

4.運行一個長時間的背景工作(根據不同平台而異)

5.使用AirDrop接收資料

 

iOS開發 之 App Extension 整體總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.