ios8發布已經有一段時間了,伴隨著ios8同時也出現了許多新的特性,ios系統將會越來越開放,這是好事。其中一個新特性就是在下拉通知欄里加入了個性的widget,開發者可以自己定義widget的樣式內容。當然這個功能在Android上早就實現了,_.........,如下圖:
首先先說幾個概念,
1、app extension:extension是iOS8新開放的一種對幾個固定系統區域的擴展機制,extension并不是一個獨立的app,它有一個包含在app bundle中的獨立bundle,extension的bundle后綴名是.appex。當然它有好多類型,如下圖官方文檔上介紹的那天,今天我們主要講解的就是Today中的,又叫做widget。
2、containing app:包含extension的app就是containning app,因為extension不能單獨存在,所以必須得依附在一個正常的app里,這樣才能提交商店。
3、host app:能夠調起extension的app被稱為host app,比如widget的host app就是Today。
我們看下它們三者之間是如何工作的,如下圖:
接下來我們具體看如何完成一個簡單的DEMO,這樣你就更加了解了,_
首先我們先新建一個工程,這一步就省略了,接下來我們增加一個target,選擇Today Extension,如下圖:
然后創建完,如下圖:
默認創建的storyboard里是hello world,所以我們先run項目,看看效果:
是不是很簡單,_。。。
那么接下來我們看下containing app跟extension如何共享數據,例如我containing app里的數據,我要在extension顯示。在這之前,我們要先講下app groups,它主要用于同一group下的app共享同一份讀寫空間,以實現數據共享。我們看下工程中如何開啟app groups,首先們選擇targets,然后選擇containing app,->Capabilities,打開app groups的開關,如下圖:
點下面的加號按鈕,新建一個group,例如:group.com.company.app,如下圖:
創建完后如下圖:
同理,選擇targets為extension,同樣創建一個app groups,選擇跟containing app一樣的名字,就是containing app里的app groups跟extension里的app groups名字相同,如下圖:
OK。。。app groups創建好后,我們就可以實現數據共享了,
第一種方法是通過NSUserDefaults,存數據代碼如下:
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:groupID];
[shared setObject:[NSNumber numberWithInt:10] forKey:@"number"];
[shared synchronize];
取數據如下:
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:groupID];
NSString *string=[NSString stringWithFormat:@"%@",[shared objectForKey:@"number"]];
_numberLabel.text=string;
我們在containing app中存一個數據,然后在extension里取一個數據,demo中我存了一個數字10,然后我們看下效果:
還有一種方法是通過NSFileManager來實現,存數據代碼如下:
NSError *err = nil;
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupID];
containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];
NSString *value =@"123";
BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
取數據代碼如下:
NSError *err = nil;
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupID];
containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];
NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&err];
對于更復雜工程里加入extension,可能需要共享代碼,你可能需要把一些公用的數據寫入自己的framework中,然后containing app跟extension中各存一個,以此來達到共用代碼,至于具體的實現,各位可以自己去嘗試嘗試_。。。
我們再看下通過點擊extension里的內容來回到containing app中,其實就是通過openurl,首先需要在containing app中創建url type,如下圖:
在extension中,寫如下代碼:
[self.extensionContext openURL:[NSURL URLWithString:@"TestWight://"] completionHandler:^(BOOL success) {
NSLog(@"open url result:%d",success);
}];
需要注意的地方是,extension中view的位置不是最左邊開始的,而是默認從icon后開始的,所以如需修改,代碼入下:
// 一般默認的View是從圖標的右邊開始的...如果你想變換,就要實現這個方法
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {
//UIEdgeInsets newMarginInsets = UIEdgeInsetsMake(defaultMarginInsets.top, defaultMarginInsets.left - 16, defaultMarginInsets.bottom, defaultMarginInsets.right);
//return newMarginInsets;
//return UIEdgeInsetsZero; // 完全靠到了左邊....
return UIEdgeInsetsMake(0.0, 16.0, 0, 0);
}
還有就是有時view里的控件看不見,所以需要添加這句話:
self.preferredContentSize = CGSizeMake(self.view.bounds.size.width, 100);
需要手動自己添加,在下拉通知里的edit里,