需求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
咱們先運行項目,在運行應用擴展
上述就完成了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、上架注意事項
若是出現打包,或上架失敗,能夠嘗試下面步驟
參考地址