iOS應用擴展(APP Extension)- Today Extension使用

需求ios

一切的結果皆是需求所產生的數據庫


筆者主要目的是想要做出下圖效果(上半部分)xcode

 

首先咱們知道這是一種Today Extension,上圖是經過3DTouch觸按彈出的,咱們也能夠在今日通知欄裏添加看到ruby

最終的效果以下:服務器

 

着重點app

一、建立Today Extension框架

二、實現擴展和宿主App之間共享數據工具

三、使用宿主App中的文件ui

四、擴展中打開宿主Appurl

五、補充:讀取xib文件、擴展中支持三方框架、參數傳遞、擴展Widget高度、上架注意事項


一、建立Today Extension

首先,咱們選中項目文件,選擇 xcode ->Editor ->Add Target,以下圖,選中Today Extension項,而後點擊Next,命名(本文中爲MyTodayWidget),在彈出框中選擇Activate,激活這個scheme

 
激活以後,項目中就會多出一個TodayWidget的擴展,新增的文件夾中的MainInterface.storyboard和TodayViewController這個類就是咱們要在通知中心顯示的界面的控制器。storyborad,裏面已經有一個默認的界面,其中只包含了一個label,顯示「Hello World」
 
TodayWidget擴展都是以宿主App前綴開始的

咱們先運行項目,在運行應用擴展

 這樣,我門能夠在系統的今日通知中心看到以下樣式

上述就完成了Today Extension的建立

固然你能夠將擴展中的plist中的displayname更換爲宿主應用名稱,在TodayViewController完成項目須要的UI


二、實現擴展和宿主App之間共享數據

在Today Extension開發中,避免不了要和宿主App之間共享數據,好比,筆者的項目中須要使用項目中的域名、三方平臺請求頭部、服務器數據地址等等;

擴展與宿主App之間共享數據有兩種方式:

1.經過NSUserDefaults

2.經過一個擴展與App均可以訪問的共享容器,來存放文件,數據(Core Data, Sqlite等均可以存放在這個共享的容器中)

首先,咱們須要建立一個app group,以下圖,選中項目的Target -> Capabilities -> App Groups,打開,若是你之前建立過group,會自動列出來。選擇+號,填入group的名稱(記下這個名稱,由於這個是擴展和宿主之間共享數據的標誌符)

 

建立完成以後,選擇擴展的Target -> Capabilities -> App Groups,打開,選擇咱們剛纔所建立的group

⚠️: 若是出現了錯誤,應該是名稱不可用,換一個重試

也能夠登陸開發中選中《App Group》建立

在擴展和宿主App打開group以後,項目中會多出兩個文件,以下圖

 
完成上述以後,咱們利用剛剛的標誌符來存取 共享的數據
// 存儲數據 [[[NSUserDefaults alloc] initWithSuiteName:@"group.com.LOLITA.appExtension"] setValue:myNote forKey:@"myShareData"]; // 取出數據 NSArray *myData = [[[NSUserDefaults alloc] initWithSuiteName:@"group.com.LOLITA.appExtension"] valueForKey:@"myShareData"]; 

這樣咱們能夠在擴展和宿主App之間存取共享的數據了

補充:

若是須要存儲更多的數據,能夠經過文件或者數據庫(Core Data, Sqlite等)。這個時候共享數據的方法就是要建立一個共享的文件夾

NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier: @"group.com.LOLITA.appExtension"]; 

經過上面的方法,擴展和App就均可以訪問這個共享的文件夾了,將數據庫,文件等存儲在這個文件夾中,也一樣的達到數據共享的目的。


三、使用宿主App中的文件

在擴展中,老是避免不了想要使用宿主項目中的文件,例如cell樣式,數據處理工具等等,重寫一份固然是能夠的,但不是咱們想要的結果。

咱們能夠將須要用的文件也供用給擴展,步驟以下

打開.m文件,選中下圖按鈕

這樣咱們就能夠在擴展中使用該文件了

⚠️:在選擇的文件中,若是包含了其餘文件,同樣是須要添加到擴展中的


四、擴展中打開宿主App

既然擴展做爲了宿主App消息的展現欄,確定應用的入口了,那麼咱們怎麼讓擴展和App之間進行消息傳遞呢?例如,咱們須要打開某條消息的詳情,或者是某個功能模塊。

咱們知道,咱們打開別的應用是須要設置URL Types,而後經過URL Schemes來打開應用的,一樣的,擴展也能夠當作是其餘應用,這樣,咱們勢必也要爲本身的App設置一個URL Types。

首頁咱們設置一個URL Types

當咱們想經過openURL來打開應用時,卻發現報錯了

這是由於擴展不是一個完整的程序,因此它並沒沒有[UIApplication sharedApplication] 這個對象。

因此Apple給每一個UIViewController加了一個extensionContext屬性,在咱們的宿主App中,這個屬性是nil,而在擴展中,咱們就能夠經過extensionContext來執行跳轉.

咱們在點擊事件中添加以下代碼

[self.extensionContext openURL:[NSURL URLWithString:@"AppExtension://add"] completionHandler:nil]; 

既然有跳轉,確定涉及到傳處理了,咱們在AppDelegate裏處理消息

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { // 能夠先回到應用首頁,在跳轉 if ([url.absoluteString hasPrefix:@"AppExtension"]) { if ([url.absoluteString hasSuffix:@"add"]) { // do something } else if ([url.absoluteString containsString:@"detail"]){ // do something } } return YES; } 

五、補充:讀取xib文件、擴展中支持三方框架、參數傳遞、擴展Widget高度、上架注意事項等

a、讀取xib文件

若是cell樣式是xib,並出現讀取錯誤問題,可使用下面代碼嘗試

NSBundle *bundle = [NSBundle bundleForClass:[TodayItemView class]]; NSArray *cells = [bundle loadNibNamed:@"TodayItemView" owner:nil options:nil]; TodayItemView *itemView = cells.firstObject; 

b、擴展中支持三方框架

若是擴展中使用到三方框架,則在Podfile中添加下面代碼,而且update

target :'MyTodayWidget' do platform :ios, '8.0' pod 'AFNetworking', '~> 3.1.0' end 

c、參數傳遞

若是須要傳遞多個參數,能夠參考下面代碼嘗試

NSString *urlString = [NSString stringWithFormat:@"AppExtension://markCode=%@&code=%@&yesclose=%@&stockName=%@",market_stockCode,stockCode,preclose_px,[stockName stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]; [self.extensionContext openURL:[NSURL URLWithString:urlString] completionHandler:nil]; 

⚠️:url中不能出現中文,須要進行UTF-8轉換,上面例子中,我將中文名稱進行了轉換,你也能夠將urlString總體進行轉換

d、url解析(接上面c)

若是url解析有問題,能夠參考下面代碼嘗試

// 將url轉爲http形式 NSString *tmpUrlString = [url.absoluteString stringByReplacingOccurrencesOfString:@"AppExtension://" withString:@"http://xxx?"]; NSURLComponents *components = [NSURLComponents componentsWithString:tmpUrlString]; NSArray* queryItems = components.queryItems; NSMutableDictionary* queryItemDict = [NSMutableDictionary dictionary]; // 將value和name轉換爲字典 for (NSURLQueryItem* item in queryItems) { [queryItemDict setObject:item.value forKey:item.name]; } 

e、擴展Widget高度

系統默認的高度爲110,若是想要在通知中心擴展高度,可使用下面代碼嘗試

- (void)viewDidLoad { [super viewDidLoad]; // 將小部件展示模型設置爲可展開 self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded; } 

完成下面代理

- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize { if (activeDisplayMode == NCWidgetDisplayModeExpanded) { // 設置展開的新高度 self.preferredContentSize = CGSizeMake(0, NewHeight); }else{ self.preferredContentSize = maxSize; } } 

⚠️:使用3DTouch喚出的彈窗依舊是110,上面代碼只是改變了通知中心的高度

f、上架注意事項

若是出現打包,或上架失敗,能夠嘗試下面步驟

  • 擴展和target中的應用包都選自動管理簽名和證書
 
 
  • 項目中配置正確的證書
 

參考地址

一、iOS開發之App Extension(應用擴展)之 -- Today Extension 

相關文章
相關標籤/搜索