1.證書配置:http://blog.csdn.net/songchunmin_/article/details/51316806
2.編碼階段:http://blog.csdn.net/songchunmin_/article/details/51291752
3.官方文檔:https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Today.html
4.國外有篇比較好的文檔:https://www.appcoda.com/app-extension-programming-today/
5.widget幾個常用功能的實現(xiàn):http://www.reibang.com/p/9b3d06236d19
術(shù)語:
主項目:往已有的A項目里添加widget残揉,那么A是主項目
Start~
環(huán)境搭建
1.蘋果后臺配置證書,下載Provisioning Profiles文件纪隙,得到4個Provisioning Profiles文件(主項目和widget分別有兩個:dev的和release的)遍膜。
注意widget項目和主項目其實是兩個獨立的appID,而通過app group來相互交互瓤湘。
2.對于主項目的配置:
(1)選擇新的pro證書
(2)打開targets-->Capabilities-->App Groups 選項瓢颅,然后選擇后臺配置的group:
3.添加widget項目。
將Bundle
Identifier改為和蘋果后臺配置的appid一樣弛说。并且注意當(dāng)時命名的時候挽懦,必須遵循如下規(guī)則:前綴要包括主項目的Bundle
Identifier。后綴不能是widget關(guān)鍵字(木人。信柿。。這里很坑醒第,試了很多次)渔嚷。然后因為我的XCode并沒有配置開發(fā)者賬號,所以將Automatically
manage singing的對勾去掉(反正證書文件都下載給你了)稠曼。
然后選擇好Provisioning Profile文件形病,dev和release的。當(dāng)前頁的error就都應(yīng)該消失了霞幅。
將Build Setting里的簽名設(shè)置好:
如果當(dāng)時在蘋果后臺配置證書的時候漠吻,deviceid都加上了你的手機,那么直接真機運行司恳,就可以在手機上看到一個“Hello World”的widget途乃。
第一次運行,可能看到左上角名字是WIDGET扔傅,這個有點延遲耍共,第二次就可以看到是“寶寶樹小時光”烫饼。
業(yè)務(wù)邏輯實現(xiàn)
1.純代碼實現(xiàn)布局:
通過以上步驟,添加的widget項目划提,使用的是Storyboard作為布局枫弟。使用純代碼需要:
(1)刪除Storyboard文件,widget項目的plist鹏往,刪除NSExtensionMainStoryboard
(2)添加NSExtensionPrincipalClass字段 并設(shè)為TodayViewController
2.TodayViewController生命周期:
經(jīng)過測試:基本上超過2秒淡诗,widget元素在屏幕上消失(手機沒有停留在widget頁面或者停留在widget頁面,沒有滑動到自己項目的widget)伊履,widget再次出現(xiàn)的時候韩容,都會重新調(diào)用ViewDidLoad。而短時間的消失再出現(xiàn)唐瀑,不會執(zhí)行ViewDidLoad而是執(zhí)行ViewWillAppear群凶。所以如果不進行處理,每次widget出現(xiàn)哄辣,就請求數(shù)據(jù)的話请梢,即時兩次數(shù)據(jù)相同也會閃一下(知乎),想不閃可以把數(shù)據(jù)緩存力穗,每次widget出現(xiàn)都加在緩存數(shù)據(jù)毅弧,并且發(fā)送請求,請求回的數(shù)據(jù)和當(dāng)前展示數(shù)據(jù)做對比当窗,如果一樣够坐,則不用刷新列表,如果不一樣則刷新列表崖面。然后緩存的機制元咙,因為一般請求的數(shù)據(jù)都是json,可以解析成dic對象巫员,使用plist進行緩存庶香,比較方便。
3.展開/折疊简识,在這個系統(tǒng)方法中設(shè)置展開脉课、折疊的高度即可,但是好像不能主動設(shè)置在什么情況下是展開的财异,在什么情況下的折疊的倘零,也就是說不能代碼控制展開還是折疊,只能是用戶點擊按鈕來展開和折疊戳寸,蘋果沒有給出那么多的自由呈驶。
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
if(activeDisplayMode == NCWidgetDisplayModeCompact) {
self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 105);
}else{
self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 495);
}
}
4.使用主項目的自定義類,以及第三方庫:
widget開發(fā)時疫鹊,肯定會遇到想使用主項目的類的情況袖瞻,只需要將要使用的類的.m文件司致,多加上一個target,選擇widget項目即可聋迎。
使用第三方庫脂矫,我的項目里暫時沒有遇到這種需求,但是通過pods維護第三方庫的時候霉晕,Podfile文件會指定每個第三方庫要加入的target庭再,那么在widget的target中,加上要使用的第三方庫牺堰,應(yīng)該就可以拄轻,可以自己試試。
5.數(shù)據(jù)共享
widget項目必然經(jīng)常要和主項目共享數(shù)據(jù)伟葫,可以通過NSUserDefault恨搓,注意和平時用有些不同,創(chuàng)建UserDefault的時候筏养,要指定groupid斧抱。上代碼:
// widget項目里取數(shù)據(jù)
+ (NSString*)widgetStringForKey:(NSString*)defaultName {
NSUserDefaults*shared = [[NSUserDefaultsalloc] initWithSuiteName:@"group.com.appname"];
return[shared stringForKey:defaultName];
}
// 主項目里存數(shù)據(jù)
+ (void)widgetSetObject:(id)value forKey:(NSString*)defaultName {
NSUserDefaults*shared = [[NSUserDefaultsalloc] initWithSuiteName:@"group.com.appname"];
[shared setObject:value forKey:defaultName];
[shared synchronize];
}
還有通過NSFileManager數(shù)據(jù)共享的方式,項目里沒有用到渐溶,可以自己查閱資料試一試辉浦。
6.喚起主項目
通過URL Schemes的方式:
(1)在主項目里配置一個對應(yīng)widget的URL。
(2)在需要喚起主項目的地方:
NSString*schemeString = [NSStringstringWithFormat:@"HMWidget://jumptab?number=%@",[NSStringencodeBase64String:@"3"]];
[self.extensionContext openURL:[NSURLURLWithString:schemeString] completionHandler:^(BOOLsuccess) {
}];
(3)在主項目appdelegate的代理方法中掌猛,截取URL,做處理:
- (BOOL)application:(UIApplication *)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation
{
if([url.description hasPrefix:@"HMWidget://"]) {
if(![HMUser isLogin]) {
returnYES;
}
return[HMSchemeUrlRouter handleScheme:url.description withAppDelegate:self];
}
}