iOS8.0之后次氨,蘋果支持了擴(kuò)展(Extension)的開發(fā)偷仿,開發(fā)者可以通過系統(tǒng)提供給我們的擴(kuò)展接入點(diǎn) (Extension point) 來為系統(tǒng)特定的服務(wù)提供某些附加的功能。當(dāng)時(shí)Widget擴(kuò)展應(yīng)用不溫不火舆绎,iOS10之后官方對Widget進(jìn)行了大幅度的優(yōu)化胞锰,配合3Dtouch Widget逐漸火了起來。本文簡單的介紹了Widget的使用葬凳。
本地大致按照以下四個(gè)步驟介紹widget
1.在宿主工程添加widget target
2.構(gòu)建UI界面
3.喚醒宿主App
4.與宿主App共享數(shù)據(jù)
1.在宿主工程添加widget target
打開宿主工程绰垂,F(xiàn)lie->New->Target->Today Extension->Next,如下圖火焰。這樣創(chuàng)建一個(gè)widget target
這個(gè)時(shí)候需要注意兩點(diǎn)
1.在當(dāng)前的widget target基本配置里面將Deployment Target設(shè)置為你要兼容的iOS最低版本劲装。
因?yàn)閯?chuàng)建出來的時(shí)候,這里是默認(rèn)是iOS最高版本昌简,如果不更改占业,你自己的手機(jī)iOS版本比Deployment Target低的話就會導(dǎo)致運(yùn)行而不出現(xiàn)widget情況。
2將你需要的圖片資源拖入當(dāng)前的target內(nèi)
因?yàn)閣idget 與 宿主App是兩個(gè)不容的進(jìn)程纯赎,資源是不能共享的谦疾,如果不推入widget會導(dǎo)致不能加載資源。當(dāng)然你也可以創(chuàng)建一個(gè)xcassets再把圖片資源拖入址否。
2.構(gòu)建UI界面
系統(tǒng)默認(rèn)是用storyboard的形式餐蔬,如果你使用純代碼需要在當(dāng)前target的info.plist首先將原有NSExtensionMainStoryboard字段刪除,添加字段NSExtensionPrincipalClass佑附,value是你所寫的controller的名稱,一般默認(rèn)的都是TodayViewController仗考,如下圖
如果使用SB那就忽略上面的操作音同。
iOS10以上支持widget的折疊與展開。
在初始化UI的時(shí)候加入下面的代碼秃嗜,告訴系統(tǒng)你的widget是可折疊的樣式权均。
if (@available(iOS 10.0, *)) {
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
重寫切換展開及折疊布局時(shí)的方法顿膨,處理用戶點(diǎn)擊折疊與展開的操作。
- (void) widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
NSLog(@"maxWidth %f maxHeight %f",maxSize.width,maxSize.height);
if (@available(iOS 10.0, *)) {
if (activeDisplayMode == NCWidgetDisplayModeCompact) {
//折疊
self.preferredContentSize = CGSizeMake(maxSize.width, 100);
//處理一些操作
} else {
//展開
self.preferredContentSize = CGSizeMake(maxSize.width, 200);
//處理一些操作
}
} else {
// Fallback on earlier versions
}
}
這里注意加載數(shù)據(jù)完畢后叽赊,渲染UI時(shí)一定要在主線程操作恋沃。
3.喚醒宿主App
widget 與 宿主App屬于兩個(gè)獨(dú)立的進(jìn)程”刂福可以理解為兩個(gè)不同的App囊咏,如果喚醒宿主,可以通過schemes的方式喚醒塔橡。
1.在宿主App內(nèi)設(shè)置url schemes
在宿主項(xiàng)目的target->info->URLTypes點(diǎn)擊加號增加內(nèi)容梅割,然后在URL Schemes定義一個(gè)Schemes,例如為widgetDemo葛家,如下圖
2.處理widget的點(diǎn)擊事件
在需要跳轉(zhuǎn)的時(shí)候加入以下代碼
//點(diǎn)擊了內(nèi)容户辞,要跳轉(zhuǎn)到宿主app
NSURL *URL = [NSURL URLWithString:@"widgetDemo://data=123456"];
[self.extensionContext openURL:URL completionHandler:^(BOOL success) {
if (success) {
NSLog(@"打開成功");
}
}];
4.與宿主App共享數(shù)據(jù)
1.通過schemes傳遞參數(shù)
如果數(shù)據(jù)量不大,僅僅是參數(shù)的一些傳遞的話癞谒,利用schemes即可底燎,如上面的代碼所示widgetDemo://后面的data=123456即是參數(shù),可以攜帶少量的信息弹砚。
2.通過App Groups來共享數(shù)據(jù)
(1.)去開發(fā)者賬號Identifiers->App Groups 點(diǎn)擊+號增加一個(gè)App Groups total.如下圖:
(2.)然后去宿主App的appId點(diǎn)擊Edit->點(diǎn)擊App Groups的Edit双仍,選中剛才創(chuàng)建的App Groups total->Continue.點(diǎn)擊如下圖
(3.)分別去Xcode中的宿主Targrt 與 widget Target,打開App Groups對剛才創(chuàng)建的App Groups total打鉤迅栅,無任何錯(cuò)誤殊校,證明添加成功,如下圖读存。
當(dāng)然你也可以忽略前兩步直接進(jìn)行第三步为流,點(diǎn)擊+號分別在宿主Targrt 與 widget Target中增加一個(gè)App Groups total,可能會因?yàn)楦袷讲粚θ貌荆鵁o法添加成功敬察。
分別在widget 內(nèi)添加寫入代碼,在宿主app內(nèi)添加讀取代碼尔当。即可完成App Groups內(nèi)數(shù)據(jù)共享
//widget內(nèi)存入數(shù)據(jù)
- (void)wirteData:(NSData *)data {
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.widgetdemo.message"];
[userDefaults setObject:data forKey:@"widgetImage"];
BOOL isok = [userDefaults synchronize];
NSLog(@"寫入成功莲祸?%d",isok);
}
//宿主app內(nèi)讀取數(shù)據(jù)
- (void)readMessage {
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.widgetdemo.message"];
NSData * date = [userDefaults objectForKey:@"widgetImage"];
_imageView.image = [UIImage imageWithData:date];
}
至此widget的簡單使用完成,Demo戳這里椭迎,下面有一些注意點(diǎn):
1.widget與宿主細(xì)胞分別是兩個(gè)不同的進(jìn)程锐帜,相當(dāng)于是兩個(gè)不同的app,上架的時(shí)候需要創(chuàng)建證書畜号,配置文件等缴阎。
2.widget與宿主細(xì)胞分別是兩個(gè)不同的進(jìn)程,圖片等資源不能直接使用宿主app的資源简软。
3.widget target基本配置里面將Deployment Target設(shè)置為你要兼容的iOS最低版本蛮拔。一定比你真機(jī)的iOS系統(tǒng)版本低述暂,否者不能顯示出來。