iOS Widget的簡(jiǎn)單實(shí)現(xiàn)

自iOS8之后因悲,蘋果支持了擴(kuò)展(Extension)的開發(fā),開發(fā)者可以通過系統(tǒng)提供給我們的擴(kuò)展接入點(diǎn) (Extension point) 來為系統(tǒng)特定的服務(wù)提供某些附加的功能讯检。今年iOS10的推出卫旱,讓W(xué)idget擴(kuò)展應(yīng)用漸漸的火了起來,地位得到重大的提升顾翼,從這也可以看出蘋果對(duì)他的重視,今天我們就來一起學(xué)習(xí)下Widget灸芳,來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的擴(kuò)展程序。

iOS Widget擴(kuò)展程序

程序效果

程序效果圖

創(chuàng)建Widget程序

  • 創(chuàng)建工程拜姿,在工程中添加擴(kuò)展程序
創(chuàng)建Widget程序
  • 創(chuàng)建成功后的目錄
創(chuàng)建成功

順便說一句砾隅,擴(kuò)展程序雖然是程序的擴(kuò)展,但是這兩個(gè)應(yīng)用其實(shí)是“獨(dú)立”的究反。準(zhǔn)確的來說,它們是兩個(gè)獨(dú)立的進(jìn)程精耐,默認(rèn)情況下互相不應(yīng)該知道對(duì)方的存在琅锻。擴(kuò)展需要對(duì)宿主 app (host app,即調(diào)用該擴(kuò)展的 app) 的請(qǐng)求做出響應(yīng)恼蓬,當(dāng)然,通過進(jìn)行配置和一些手段小槐,我們可以在擴(kuò)展中訪問和共享一些容器 app 的資源,這個(gè)我們稍后再說凿跳。

Widget布局方式

  • 使用Interface Builder
    工程默認(rèn)的方式就是使用Interface Builder,如果實(shí)現(xiàn)簡(jiǎn)單的布局的話可以考慮這種方式控嗜。
  • 使用代碼進(jìn)行布局
    當(dāng)涉及到比較復(fù)雜的UI布局的時(shí)候,可以考慮使用這種布局方式曾掂,按大家平時(shí)的習(xí)慣來壁顶。這里需要注意一下,如果需要使用代碼布局的話需要修改一下plist文件博助。
    首先將原有NSExtensionMainStoryboard字段刪除,添加字段NSExtensionPrincipalClass蛔糯,value是你所寫的controller的名稱窖式,一般默認(rèn)的都是TodayViewController
修改plist文件

實(shí)現(xiàn)相應(yīng)的方法

1. 設(shè)置Widget的size
iOS10之后,Widget支持展開及折疊兩種展現(xiàn)方式萝喘,通過設(shè)置widgetLargestAvailableDisplayMode屬性可以讓W(xué)idget程序?qū)崿F(xiàn)展開布局。如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    if (isIOS10)
    {
        self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
    }
    
    self.preferredContentSize = CGSizeMake(kWidgetWidth, 110);
}

2. 重寫切換展開及折疊布局時(shí)的方法(iOS10之后)

- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize
{
    NSLog(@"maxWidth %f maxHeight %f",maxSize.width,maxSize.height);
    
    if (activeDisplayMode == NCWidgetDisplayModeCompact)
    {
        self.preferredContentSize = CGSizeMake(maxSize.width, 110);
    }
    else
    {
        self.preferredContentSize = CGSizeMake(maxSize.width, 200);
    }
}

3. iOS10之前爬早,視圖原點(diǎn)默認(rèn)存在一個(gè)間距启妹,可以實(shí)現(xiàn)以下方法來調(diào)整視圖間距
注:該方法在iOS10之后被遺棄,iOS10默認(rèn)不存在間距饶米。

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
    return UIEdgeInsetsMake(0, 10, 0, 10);
}

應(yīng)用喚醒

本來想叫應(yīng)用間跳轉(zhuǎn)的,想想還是這個(gè)名字比較高大上些??
如下照瘾,配置url scheme丧慈,這個(gè)定義的時(shí)候盡量不要和其他用用沖突,筆者定義的為WidgetDemo。這樣,通過訪問WidgetDemo://就可以實(shí)現(xiàn)應(yīng)用喚醒了笑旺。代碼如下:

配置url scheme
- (void)redButtonPressed:(UIButton *)button
{
    NSLog(@"%s",__func__);
    
    NSURL *url = [NSURL URLWithString:@"WidgetDemo://red"];
    
    [self.extensionContext openURL:url completionHandler:^(BOOL success) {
        
        NSLog(@"isSuccessed %d",success);
    }];
}

相應(yīng)的,在AppDelegate中實(shí)現(xiàn)以下方法关噪,這里可以處理傳過來的action乌妙,對(duì)于傳過來不同的值可以進(jìn)行不同的操作,這里我們打印了請(qǐng)求url的內(nèi)容藤韵。

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    if ([[url absoluteString] hasPrefix:@"WidgetDemo"])
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:@"你點(diǎn)擊了%@按鈕",[url host]] delegate:nil cancelButtonTitle:@"好的??" otherButtonTitles:nil, nil];
        [alert show];
    }
    return  YES;
}
  • 簡(jiǎn)易的應(yīng)用快速啟動(dòng)器
    既然說到了應(yīng)用喚醒,這里再稍稍拓展以下欲险,想必大家都有用過類似launcher這種的應(yīng)用快速啟動(dòng)器匹涮。其實(shí)就是運(yùn)用了應(yīng)用間跳轉(zhuǎn)的原理天试,每款應(yīng)用都有自定義的url scheme然低,我們只要知道他們的url scheme就可以跳轉(zhuǎn)至改款應(yīng)用,例如進(jìn)行微信的跳轉(zhuǎn):
- (void)wechatLoginButtonPressed
{
    NSLog(@"%s",__func__);
    
    NSURL *url = [NSURL URLWithString:@"wechat://"];
    
    [self.extensionContext openURL:url completionHandler:^(BOOL success) {
        
        NSLog(@"isSuccessed %d",success);
    }];
}

以下是我們比較常用的軟件的url scheme带兜,有興趣的同學(xué)們可以試一試:
QQ mqq:// 微信 weixin:// 淘寶taobao:// 微博 sinaweibo:// 支付寶alipay://

數(shù)據(jù)共享

擴(kuò)展程序一般都不是脫離宿主程序單獨(dú)運(yùn)行的吨灭,難免需要和宿主程序進(jìn)行數(shù)據(jù)交互。而相對(duì)于一般的APP沃于,數(shù)據(jù)可以用單例,NSUserDefault等等檩互。但由于拓展與宿主應(yīng)用是兩個(gè)完全獨(dú)立的App,并且iOS應(yīng)用基于沙盒的形式限制闸昨,所以一般的共享數(shù)據(jù)方法都是實(shí)現(xiàn)不了數(shù)據(jù)共享,這里就需要使用App Groups饵较。

  • 在宿主程序和擴(kuò)展程序中分別設(shè)置打開App Group,設(shè)置一個(gè)group的名稱横辆,這里要保證宿主APP和擴(kuò)展APP的groupName要是相同的茄猫。
設(shè)置App Group

兩種數(shù)據(jù)存儲(chǔ)方式

  • 使用NSUserDefault
    這里不能使用[NSUserDefaults standardUserDefaults];方法來初始化NSUserDefault對(duì)象,正像之前所說划纽,由于沙盒機(jī)制,拓展應(yīng)用是不允許訪問宿主應(yīng)用的沙盒路徑的靖避,因此上述用法是不對(duì)的,需要搭配app group完成實(shí)例化UserDefaults比默。正確的使用方式如下:
    寫入數(shù)據(jù)
    NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.japho.widgetDemo"];
    [userDefaults setObject:self.textField.text forKey:@"widget"];
    [userDefaults synchronize];

讀取數(shù)據(jù)

    NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.japho.widgetDemo"];
    self.contentStr = [userDefaults objectForKey:@"widget"];
  • 通過NSFileManager共享數(shù)據(jù)
    寫入數(shù)據(jù)
-(BOOL)saveDataByNSFileManager
{
    NSError *err = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxx"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/ widget"];
    NSString *value = @"asdfasdfasf";
    BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
    if (!result)
    {
        NSLog(@"%@",err);
    }
    else
    {
        NSLog(@"save value:%@ success.",value);
    }
    return result;
}

讀取數(shù)據(jù)

-(NSString *)readDataByNSFileManager
{
    NSError *err = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxx"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/ widget"];
    NSString *value = [NSString stringWithContentsOfURL:containerURL encoding: NSUTF8StringEncoding error:&err];
    return value;
}

其他

補(bǔ)充:widget的上線也是需要單獨(dú)申請(qǐng)APP ID的 需要配置證書和Provisioning Profiles文件
沒有配置相關(guān)證書時(shí):



配置證書及描述文件:(列舉一些)




證書與描述文件配置好之后:

Demo

博主雙手奉上demo粘咖,同學(xué)們?nèi)绻矚g就給我點(diǎn)個(gè)star吧~~ ??

最后感謝一下文章的博主??

Widget的簡(jiǎn)單應(yīng)用并適配iOS10
iOS開發(fā)------Widget(Today Extension)插件化開發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侈百,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子钝域,更是在濱河造成了極大的恐慌,老刑警劉巖路呜,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件织咧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡笙蒙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門轧葛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搂抒,“玉大人尿扯,你說我怎么就攤上這事≈运瘢” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)档插。 經(jīng)常有香客問我,道長(zhǎng)晨抡,這世上最難降的妖魔是什么则剃? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮棍现,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘己肮。我一直安慰自己,他們只是感情好娄柳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布艘绍。 她就那樣靜靜地躺著,像睡著了一般诱鞠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上航夺,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音墓造,去河邊找鬼。 笑死觅闽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛉拙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吮廉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼畸肆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轴脐,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恬涧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溯捆,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厦瓢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旷痕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡售碳,死狀恐怖绞呈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情佃声,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布圾亏,位于F島的核電站封拧,受9級(jí)特大地震影響夭问,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缰趋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望味抖。 院中可真熱鬧,春花似錦仔涩、人聲如沸谋竖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)韧骗。三九已至,卻和暖如春袍暴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背政模。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耗式,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓刊咳,卻偏偏與公主長(zhǎng)得像儡司,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捕犬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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