在說widget開發(fā)前,先來了解下APP Extensions和App Groups:
一观堂、關(guān)于App Extensions
extension是iOS8新開放的一種對幾個固定系統(tǒng)區(qū)域的擴展機制让网,它可以在一定程度上彌補iOS的沙盒機制對應(yīng)用間通信的限制。
extension的出現(xiàn)师痕,為用戶提供了在其它應(yīng)用中使用我們應(yīng)用提供的服務(wù)的便捷方式溃睹,比如用戶可以在Today的widgets中查看應(yīng)用展示的簡略信息,而不用再進到我們的應(yīng)用中胰坟,這將是一種全新的用戶體驗因篇;但是extension的出現(xiàn)可能會減少用戶啟動應(yīng)用的次數(shù)。
了解幾個關(guān)鍵詞
extension point:
系統(tǒng)中支持extension的區(qū)域笔横,extension的類別也是據(jù)此區(qū)分的竞滓,iOS上共有Today、Share吹缔、Action商佑、Photo Editing、Storage Provider等多種厢塘,其中Today中的extension又被稱為widget茶没。
每種extension point的使用方式和適合干的活都不一樣,因此不存在通用的extension晚碾。
app extension:
extension并不是一個獨立的app抓半,它有一個包含在app bundle中的獨立bundle,extension的bundle后綴名是.appex迄薄。其生命周期也和普通app不同(后文將會描述)琅关。
extension不能單獨存在,必須有一個包含它的containing app讥蔽。
extension需要用戶手動激活涣易,不同的extension激活方式也不同,比如: 比如Today中的widget需要在Today中激活和關(guān)閉冶伞;
containing app:
盡管蘋果開放了extension新症,但是在iOS中extension并不能單獨存在,要想提交到AppStore响禽,必須將extension包含在一個app中提交徒爹,并且app的實現(xiàn)部分不能為空,這個包含extension的app就叫containing app。
extension會隨著containing app的安裝而安裝芋类,同時隨著containing app的卸載而卸載隆嗅。
host app
能夠調(diào)起extension的app被稱為host app,比如widget的host app就是Today侯繁。
extension和containing app之間的關(guān)系:
1胖喳、不能直接通信:盡管extension的bundle是放在containing app的bundle中,但是他們是兩個完全獨立的進程贮竟,之間不能直接通信丽焊。不過extension可以通過openURL的方式啟動containing app(當(dāng)然也能啟動其它app)较剃,不過必須通過extensionContext借助host app來實現(xiàn):
- (void)jumpToWidgetAPP:(UIButton *)sender {
[self.extensionContext openURL:[NSURL URLWithString:@"WidgetDemo://xxx"] completionHandler:^(BOOL success) {
NSLog(@"open url result: %d",success);
}];
}
2、可以共享資源數(shù)據(jù):extension和containing app可以共同讀寫一個被稱為Shared resources的存儲區(qū)域技健,這是通過App Groups實現(xiàn)的写穴,后文將會詳述。
3雌贱、containing app能夠控制extension的出現(xiàn)和隱藏:
讓隱藏的插件重新顯示YES/隱藏NO
[[NCWidgetController widgetController] setHasContent:YES forWidgetWithBundleIdentifier:@"com.w.app.extension"];
extension和containing app以及host app三者之間的關(guān)系:
三者之間的關(guān)系可以用官網(wǎng)的兩張圖片形象說明;
二啊送、關(guān)于App Groups
App Groups是iOS8新開放的功能,在OS X上早就可用了帽芽,它主要用于同一group下的app共享同一份讀寫空間删掀,以實現(xiàn)數(shù)據(jù)共享。extension和containing app共同讀寫一份數(shù)據(jù)是很合理的需求导街,比如系統(tǒng)的股市應(yīng)用披泪,widget和app中都需要展示幾個公司的股票數(shù)據(jù),這就可以通過App Groups實現(xiàn)搬瑰。(如何開啟以及使用App Groups下文會說明 )
三款票、widget開發(fā)過程:
接下來我們從環(huán)境搭建和業(yè)務(wù)邏輯實現(xiàn)兩大方面來說一下widget開發(fā)的過程:(接下來的提到的主項目即為上面說到的containing app)
環(huán)境搭建:
1、添加widget項目
在APP中選擇target-》 添加一個類型為Today Extension的工程泽论,就是我們想要的widget艾少;含有widget的app目錄結(jié)構(gòu)如下:
2、配置證書
由于widget項目和主項目其實是兩個獨立的appID翼悴,因為需要單獨給widget配置證書缚够,配置證書的過程參考APP證書配置;
3鹦赎、開啟APP Groups
開啟APP Groups是為了widget和app之間實現(xiàn)數(shù)據(jù)共享谍椅;為了便于后續(xù)操作,請先確保你的開發(fā)者賬號在Xcode上處于登錄狀態(tài)古话。
在app中開啟:
TARGETS-->AppExtensionDemo-->Capabilities-->App Groups
找到以后雏吭,將App Groups右上角的開關(guān)打開,然后選擇添加groups,注意命名要規(guī)范陪踩,比如:group.com.company.app;
在extension中開啟:假設(shè)創(chuàng)建widget target的名稱為TodayExtension杖们,對應(yīng)的App Group位于
TARGETS-->TodayExtension-->Capabilities-->App Groups
開啟的方式和APP中一樣,注意必須要保證這里的App Groups名稱和APP中相同肩狂。
業(yè)務(wù)邏輯實現(xiàn):
搭建好開發(fā)環(huán)境后接下來主要從幾個功能實現(xiàn)的角度來談?wù)勅绾芜M行widget開發(fā)摘完。
1、純代碼實現(xiàn)布局
widget項目默認是使用storyboard作為布局的傻谁,如果喜歡用純代碼實現(xiàn)布局描焰,則需要做如下處理:
(1)刪除Storyboard文件,并在widget項目的plist,刪除NSExtensionMainStoryboard荆秦;
(2)添加NSExtensionPrincipalClass字段 并設(shè)為TodayViewController;
2力图、設(shè)置展開/折疊:
在系統(tǒng)提供的方法中設(shè)置widget展開/折疊的高度步绸,即可實現(xiàn)widget的展開/折疊,但是不能主動設(shè)置在什么情況下是展開的吃媒,在什么情況下的折疊的瓤介,也就是說不能代碼控制展開還是折疊,只能是用戶點擊按鈕來展開和折疊赘那,蘋果沒有給出那么多的自由刑桑。
3、共享數(shù)據(jù)
widget做為主項目的擴展募舟,必然要經(jīng)常和主項目共享數(shù)據(jù)祠斧,上面我們已經(jīng)提到可以通過App Groups來進行數(shù)據(jù)共享,具體實現(xiàn)上主要有NSUserDefault和NSFileManager兩種方式進行數(shù)據(jù)共享拱礁。
3.1 通過NSUserDefaults共享數(shù)據(jù)
主項目中存數(shù)據(jù):通過以下方式向NSUserDefaults中保存數(shù)據(jù):需要注意的是:
1琢锋、保存數(shù)據(jù)的時候必須指明group id;
2呢灶、而且要注意NSUserDefaults能夠處理的數(shù)據(jù)只能是可plist化的對象吴超,詳情見Property List Programming Guide。
3鸯乃、為了防止出現(xiàn)數(shù)據(jù)同步問題鲸阻,不要忘記調(diào)用[shared synchronize];
widget項目中取數(shù)據(jù) :對應(yīng)的讀取數(shù)據(jù)方式:
3.2 通過NSFileManager共享數(shù)據(jù)
主項目中存數(shù)據(jù):
widget項目中取數(shù)據(jù):
4、使用主項目的自定義類缨睡,以及第三方庫
widget開發(fā)時鸟悴,肯定會遇到想使用主項目的類的情況,只需要將要使用的類的.m文件宏蛉,多加上一個target遣臼,選擇widget項目即可。(如圖)
使用主項目中的第三方庫:
我們知道拾并,通過pods維護第三方庫的時候Podfile文件會指定每個第三方庫要加入的target揍堰,因此Widget如果想使用第三方庫,只需要在在widget的target中嗅义,加上要使用的第三方庫即可屏歹;
target 'CSMBP-Widget' do
pod 'AFNetworking', '3.1.0'
end
5、喚起主項目
可以通過URL Schemes的方式從widget項目跳轉(zhuǎn)到APP中之碗;
(1)在主項目里配置一個對應(yīng)widget的URL:
(2)在需要喚起主項目的地方通過self.extensionContext來實現(xiàn)跳轉(zhuǎn):
[self.extensionContext openURL:[NSURL URLWithString:@"WidgetDemo://xxx"] completionHandler:^(BOOL success) {
NSLog(@"open url result: %d",success);
}];
(3)在主項目appdelegate的openURL代理方法中蝙眶,截取URL并做處理:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
if ([url.description hasPrefix:@"WidgetDemo://"]) {
// 根據(jù)url處理具體跳轉(zhuǎn)頁面
}
return YES;
}