從iOS8開始, 系統(tǒng)開始支持iOS Widget,就是如下圖.
Widget是Extension的一種Today, WWDC2014 Session 205, 講的就是關于Extensions的開發(fā).
用一個話回答,Widget是什么呢?
Widget就是一個依賴于Container App的另外一個小App.
它有自己Bundle Id,有自己的生命周期.
新建Today Extension Target, 命名為TodayWidget,如下圖.
會產(chǎn)生如下的文件夾:
運行后(注意沒有Widget,則需要在編輯中手動添加),產(chǎn)生如圖
這里有個設計問題, 折疊的高度是固定的, 開發(fā)者改不了.
具體開發(fā)中有以下注意點:
一. 設置widgetLargestAvailableDisplayMode
及拉起
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//不設置,iOS10,可能不會出現(xiàn)展開/折疊按鈕
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
//使用open Url拉起方式
- (void)openContainingAPPWithURL:(NSString *)urlStr{
//通過extensionContext借助host app調起app
NSURL *url = [NSURL URLWithString:urlStr.length>0?[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]:@"TodayWidgetTest://"];
[self.extensionContext openURL:url completionHandler:nil];
}
二. iOS9版本差異
每次進入today頁面都會調用這個方法刷新數(shù)據(jù),但是iOS9卻不會(-_-)???一臉懵逼的什么鬼,事實就是這樣.
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler;
所以iOS9我們要自己手動調用一下
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.9
&& [[[UIDevice currentDevice] systemVersion] floatValue] > 8.9) {
[self widgetPerformUpdateWithCompletionHandler:^(NCUpdateResult result) {}];
}
}
三. TodayWidget文件夾中代碼或者其他資源(例如圖片等)和外部的是不可共用.嘗試調用外部的代碼會產(chǎn)生編譯鏈接錯誤.
解決方法:
- 如果使用cocoapods的話,直接設置好target引用就可以共用庫了. 例如下:
target "TodayExtension" do
pod 'FMDB' , '2.5'
pod 'Masonry', '0.6.4'
end
- 將共用的資源制作成framework來共用.
- 一般Widget都是輕量,共用代碼不太多,使用手動添加共享資源更加方便快捷. 如下圖手動添加藍色圈里的代碼和圖庫:
注意共享的源文件需要放在工程的根目錄下,同級于兩個target名文件夾的目錄,否則編譯器會找不到,編譯會失敗.
三. 共享數(shù)據(jù),需要將Apps建立Group關系.
- 在蘋果開發(fā)者個人中心端的工作, 戳我直達:
1, 新建App Groups,點擊下圖的選項,按提示操作.
例如建好一個ID為group.testxx.todaywidget的App Group如下:
2, 將App加入到App Group
選中要加入的App Group的App ID,點擊編輯,然后開啟App Group:
點擊App Group的編輯按鈕:
勾選Group:
將Widget的App ID也加入這個Group.
如果有其他需要共享數(shù)據(jù)的Extension也加進去.
3, 產(chǎn)生新的Provisioning Profiles并在Xcode中使用.
- 在Xcode中對應設置
1, 設置App Group,在這個Group的Target都需要設定.
2,使用對應的Provisioning Profiles,在這個Group的Target都需要設定.
沒有的話,preferences下載一下:
- 在代碼中使用共享Group沙盒
1, 沙盒地址如下(Group ID與上面保持一致):
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.testxx.todaywidget"];
2, 共享的UserDefaults(Group ID與上面保持一致):
NSUserDefaults* userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.testxx.todaywidget"];
3, 要使用共享keychain數(shù)據(jù),要另外開啟Keychain Sharing. (由于沒這種需求,暫不展開)
關于實時共享數(shù)據(jù),可以參考這位童鞋的心得.(戳我)
Widget空白及無法加載
Widget一直空白的原因很可能是崩潰了,在崩潰日志中能夠找到.
開發(fā)非常注意穩(wěn)定性,一旦崩潰了,比較難恢復了.Widget無法加載的原因,很可能是內存占用過大了.
畢竟Widget不停地運行,要注意內存控制,不宜數(shù)據(jù)量過大的任務,展示過大的圖片.(目前只展示了一張圖片,只有100K左右, 沒出現(xiàn)無法加載的現(xiàn)象)