【8】iOS開發(fā)·Widget

一、什么是Widget組件?

widget是一個(gè)依附于App的小組件顺少,可以視作一個(gè)獨(dú)立的小App王浴,但又與主App關(guān)聯(lián),在很多情況下可方便人們使用氓辣。例:天氣、支付寶筛婉、今日頭條等的小組件。

二、Widget的創(chuàng)建
1响蓉、相關(guān)證書配置

① App的證書配置:和普通證書配置一樣,可參考iOS開發(fā)·證書配置

② Widget的證書配置:

1枫甲、創(chuàng)建App Group扼褪,信息填寫完畢后一路continue下去粱栖;


創(chuàng)建AppGroup.png
填寫AppGroup的信息.png

注意:AppGroup的ID需要以group開頭
示例:group.xxx.xxx.xxx
2话浇、App的App IDs開啟App Group權(quán)限,并編輯綁定闹究;

App開啟AppGroup權(quán)限1.png
App開啟AppGroup權(quán)限2.png
App開啟AppGroup權(quán)限3.png

3幔崖、創(chuàng)建Widget的App IDs,并且綁定同一個(gè)App Group渣淤;
注意點(diǎn):
① Widget的Bundle ID需要在App的Bundle ID的基礎(chǔ)上添加赏寇;

例:App的Bundle ID是com.FanXG.Basic;
Widget的Bundle ID是com.FanXG.Basic.xxx价认;

② 在創(chuàng)建Widget的App IDs時(shí)候嗅定,勾選App Group,當(dāng)然也可以創(chuàng)建后再勾選用踩;

Widget創(chuàng)建AppIDs.png

③ 創(chuàng)建完成后渠退,和App的App IDs開啟App Group權(quán)限步驟一樣,綁定App Group脐彩;

4碎乃、分別創(chuàng)建APP、Widget的證書配置文件

創(chuàng)建配置文件.png

5丁屎、下載開發(fā)證書荠锭、發(fā)布證書、配置證書等晨川,在此不加說明证九;

========================證書配置完成========================

2、創(chuàng)建widget工程

widget是一個(gè)依附于app的小組件共虑,若想創(chuàng)建某個(gè)項(xiàng)目的widget愧怜,需新建Target

創(chuàng)建Target.png
創(chuàng)建Target2.png

創(chuàng)建完畢之后,多出MyTarget目錄

Target文件目錄.png

配置項(xiàng)目證書

配置App項(xiàng)目證書.png
配置Widget項(xiàng)目證書.png

分別開啟項(xiàng)目App Group權(quán)限妈拌,Widget的權(quán)限開啟也是一樣拥坛;
點(diǎn)擊MyTarget->Capabilities->App Groups

項(xiàng)目開啟AppGroup權(quán)限.png
3、修改布局方式

widget默認(rèn)為xib布局尘分,需要代碼布局猜惋,則需要進(jìn)行以下修改:
① 刪除MainInterface.storyboard文件
② 修改widget的info.plist文件
· 刪除NSExtensionMainStoryboard字段
· 添加NSExtensionPrincipalClass字段著摔,value是你所寫的controller的名稱定续,默認(rèn)TodayViewController

修改info文件.png

注意:
widget雖然和項(xiàng)目是一個(gè)整體的工程,但是文件和圖片是不互通的恩掷,若有一張圖片在app路徑下面黄娘,你在widget使用是讀取不到的寸宏。所以如果有什么布局想復(fù)用氮凝,需要在widget的文件下也復(fù)制一份罩阵。

4稿壁、小部件的布局

在TodayViewController中傅是,通用的組件都可以使用蕾羊,但是tableview等一系列滾動(dòng)視圖是無法滾動(dòng)的龟再,所以使用tableview布局要注意高度利凑,是不能滾動(dòng)的。

iOS10之后哀澈,Widget支持展開及折疊兩種展現(xiàn)方式割按,通過設(shè)置widgetLargestAvailableDisplayMode屬性可以讓W(xué)idget程序?qū)崿F(xiàn)展開布局哲虾。
在左滑到widget顯示的時(shí)候,會(huì)調(diào)用viewWillAppear晒旅,這時(shí)候可以去刷新獲取最新數(shù)據(jù)废恋。

展開扒寄、縮回代碼示例:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}

- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
    if (activeDisplayMode == 0) {
        self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 105);
    }else {
        self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 220);
    }
}
三迄本、App和Widget的傳值
1嘉赎、Widget跳轉(zhuǎn)到App

① 配置跳轉(zhuǎn)的URL

配置跳轉(zhuǎn)的URL.png

② 代碼示例

TodayViewController.m文件

- (void)createButton {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setFrame:CGRectMake(10, 10, 160, 50)];
    [button setTitle:@"測(cè)試示例" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(clickButtonAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)clickButtonAction {
    NSString *urlString = [NSString stringWithFormat:@"WidgetMain://"];
    NSURL *url = [NSURL URLWithString:urlString];
    [self.extensionContext openURL:url completionHandler:^(BOOL success) {
        
    }];
}

AppDelegate.m文件

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    if ([url.description hasPrefix:@"WidgetMain"]) {
        //處理widget的傳值
    }
    return YES;
}
2、NSUserDefault傳值(不推薦)

NSUserDefaults寫入代碼:

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.FanXG.Basic"];
[userDefaults setObject:@"測(cè)試舉例" forKey:@"widget"];
[userDefaults synchronize];

NSUserDefaults讀取代碼:

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.FanXG.Basic"];
NSString *contentStr = [userDefaults objectForKey:@"widget"];
NSLog(@"contentStr == %@",contentStr);

注意:
利用NSUserDefaults傳值在iOS10之后可能會(huì)報(bào)錯(cuò)靶橱,報(bào)錯(cuò)內(nèi)容:

Couldn't read values in CFPrefsPlistSource<0x2815c6d80> (Domain: group.com.FanXG.Basic, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd

這是因?yàn)樯澈袡C(jī)制关霸,拓展應(yīng)用不允許訪問宿主應(yīng)用的沙盒路徑谒拴,因此上述用法失效英上,所以我們需要配合appGroup完成實(shí)例化UserDefaults苍日;

3窗声、NSFileManager傳值(推薦)

App寫入示例代碼:

- (void)updateWidgetData {
    //獲取到共享數(shù)據(jù)的文件地址
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.FanXG.Basic"];
    NSURL *birthdayContainerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/birthday.json"];
    //將需要存儲(chǔ)的數(shù)據(jù)寫入到該文件中
    NSString *jsonString = @"需要寫入的數(shù)據(jù)或者json字符等";
    //寫入數(shù)據(jù)
    NSError *err = nil;
    BOOL result = [jsonString writeToURL:birthdayContainerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
    if (!result) {
        NSLog(@"%@",err);
    }else {
        NSLog(@"save value:%@ success.",jsonString);
    }
}

Widget讀取數(shù)據(jù)示例代碼:

- (NSString *)readDataByNSFileManager {
    NSError *err = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.FanXG.Basic"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/birthday.json"];
    NSString *value = [NSString stringWithContentsOfURL:containerURL encoding: NSUTF8StringEncoding error:&err];
    return value;
}
四拦耐、注意事項(xiàng)
  1. 主App和widget分別獨(dú)立,因此需要兩套證書扫俺,再通過App Group相互綁定狼纬;
  2. widget的Bundle ID需要再App的Bundle ID的基礎(chǔ)上添加疗琉;
舉例:
The App Bundle ID is ---- com.FanXG.Basic
The widget Bundle ID is ---- com.FanXG.Basic.OurTarget
  1. 建議將widget的版本號(hào)和構(gòu)建版本號(hào)設(shè)置的和App一致盈简,不然提交到App Store的時(shí)候會(huì)出現(xiàn)警告送火,雖然不影響提交審核和正常使用种吸,但還是設(shè)置成一樣的吧坚俗!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猖败,一起剝皮案震驚了整個(gè)濱河市降允,隨后出現(xiàn)的幾起案子剧董,更是在濱河造成了極大的恐慌,老刑警劉巖尉剩,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異皂林,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)童社,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門呀癣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來项栏,“玉大人沼沈,你說我怎么就攤上這事列另∫逞茫” “怎么了店乐?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵腺兴,是天一觀的道長(zhǎng)页响。 經(jīng)常有香客問我伏穆,道長(zhǎng)陪腌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮诗鸭,結(jié)果婚禮上染簇,老公的妹妹穿的比我還像新娘。我一直安慰自己强岸,他們只是感情好锻弓,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蝌箍,像睡著了一般青灼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妓盲,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天杂拨,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丽已,可吹牛的內(nèi)容都是我干的策州。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼尘奏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎臂外,沒想到半個(gè)月后橘霎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓦盛,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年哆致,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了踪蹬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枝缔。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖波闹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乖坠,受9級(jí)特大地震影響徐许,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翘单,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望权逗。 院中可真熱鬧斟薇,春花似錦、人聲如沸了讨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泉瞻。三九已至鞭达,卻和暖如春叨襟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梆暮。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工服协, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啦粹。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓偿荷,卻偏偏與公主長(zhǎng)得像窘游,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跳纳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容