揭秘 iOS App Extension 開(kāi)發(fā) —— Today 篇

從 iOS 8 開(kāi)始,蘋(píng)果引入了全新的 App Extension岭粤,涉及到方方面面惜索,例如今日面板、鍵盤(pán)剃浇、內(nèi)容攔截器巾兆、分享動(dòng)作等。但是官方對(duì)于 App Extension 的開(kāi)發(fā)指南少之又少虎囚,入門(mén)起來(lái)會(huì)有很多坑角塑。所以我準(zhǔn)備寫(xiě)一系列文章來(lái)幫助大家更好入門(mén) App Extension 的開(kāi)發(fā),也能少走彎路淘讥。

何為 App Extension圃伶?

顧名思義,它是一種擴(kuò)展蒲列,很類(lèi)似于一些大型軟件(好吧窒朋,現(xiàn)在可能是個(gè)應(yīng)用都可以有)的插件機(jī)制。App Extension 事實(shí)上并不是你應(yīng)用的插件蝗岖,而是系統(tǒng)的插件侥猩,其生命周期是由系統(tǒng)來(lái)管理的,所以如果你想做什么壞事還是行不通的...但是 App Extension 分發(fā)的載體是應(yīng)用抵赢,也就是說(shuō)如果你只是單純想做一個(gè)今日面板插件欺劳,也需要有個(gè)主程序,你的主程序可以什么都不做铅鲤,也可以提供一些基本的設(shè)置和數(shù)據(jù)划提。

App Extension 和主程序的關(guān)系?

可以說(shuō)沒(méi)有什么關(guān)系邢享,基本上就是兩個(gè)獨(dú)立的程序鹏往,你的主程序既不可以訪(fǎng)問(wèn) App Extension 的代碼,也不可以訪(fǎng)問(wèn)其存儲(chǔ)空間骇塘,這完完全全就是兩個(gè)進(jìn)程掸犬、兩個(gè)程序袜漩。這時(shí)你可能會(huì)問(wèn),我擦湾碎,都不能交互那有什么卵用?奠货?別急介褥,后面我會(huì)講到如何做一些交互。

App Extension 可以干什么递惋?不可以干什么柔滔?

基本上什么都能干,有人不是在今日面板里把 Chrome 的恐龍小彩蛋硬塞進(jìn)去了嗎萍虽?還有拿輸入法當(dāng)瀏覽器作分屏多任務(wù)的...只有你想不到睛廊,沒(méi)有你做不到......誒等等,有些還是做不到的杉编。比如超全,內(nèi)存有限制,App Extension 的可用內(nèi)存遠(yuǎn)不如常規(guī)應(yīng)用邓馒,以至于如果你真想做游戲嘶朱,還是掂量掂量你的資源占用問(wèn)題能不能解決吧。而且還不能訪(fǎng)問(wèn) UIApplication光酣,因?yàn)樗娜萜鲬?yīng)用是系統(tǒng)疏遏,你拿系統(tǒng)的 UIApplication 想干嘛...(當(dāng)然,你可以用遞歸查找 UIResponder 的方法拿到 UIApplication救军,但是我沒(méi)試過(guò))再次财异,你不能執(zhí)行長(zhǎng)時(shí)間的操作,你的 App Extension 可能隨時(shí)被系統(tǒng) Kill 掉唱遭,who knows?

還有更多不可用的 API 可以看這個(gè)蘋(píng)果官方文檔:Understand How an App Extension Works

開(kāi)始創(chuàng)建一個(gè) App Extension

首先看一下我們要做的東西戳寸,是一個(gè)簡(jiǎn)單 Todo 應(yīng)用,主程序長(zhǎng)這個(gè)樣:


今日面板插件長(zhǎng)這個(gè)樣:


界面都很簡(jiǎn)單啦~
主程序?qū)崿F(xiàn)其實(shí)很簡(jiǎn)單胆萧,就是 Table View 的使用以及數(shù)據(jù)持久化庆揩,這里就不著重講了。但注意跌穗,我們要留出一個(gè)接口給今日面板订晌,假設(shè)這里我們要在今日面板里顯示前 4 條待辦事項(xiàng),我們必須要單獨(dú)將這 4 條存在一個(gè)主程序和擴(kuò)展都能訪(fǎng)問(wèn)的地方蚌吸。后面我會(huì)說(shuō)怎么做锈拨。

Tips:


蘋(píng)果的 HIG 明確指出,不要在今日面板里使用可以滾動(dòng)的 Scroll View羹唠,而是要完全展開(kāi)奕枢,因此對(duì)于多條數(shù)據(jù)娄昆,我們要不就分頁(yè),要不就只顯示前幾項(xiàng)缝彬。

下面萌焰,我們就為工程創(chuàng)建一個(gè) Today Extension:


一路下一步,輸入一個(gè)子項(xiàng)目名谷浅,點(diǎn) 『Finish』就完成 Today Extension 的添加了扒俯。

這個(gè)子項(xiàng)目的初始目錄結(jié)構(gòu)如下:


P.S. 那個(gè) entitiements 文件是后來(lái)創(chuàng)建的,一開(kāi)始不會(huì)有

然后我們?cè)?Storyboard 里把大致界面拖出來(lái)一疯,如果畫(huà)布大小不合適可以在這調(diào)整一下撼玄,但是也就是調(diào)整了預(yù)覽效果,真實(shí)的大小不能在 IB 里修改墩邀。


那我們?cè)趺葱薷囊晥D在今日面板里的大小呢掌猛?答案是修改 View Controller 的 preferredContentSize 屬性,不理會(huì) width眉睹,調(diào)整 height 到合適的大小即可荔茬,因?yàn)閷挾瓤偸呛推聊粚挾认嗤摹?/p>

在這個(gè)例子中,我使用 44 * 項(xiàng)目數(shù)量 - 1 來(lái)作為視圖高度辣往,因?yàn)橐粋€(gè)標(biāo)準(zhǔn) Table View Cell 的高度是 44兔院,然后減掉最后一個(gè)條目分割線(xiàn)的高度就是我們理想的合適高度。

主程序向 App Extension 共享數(shù)據(jù)

我們?cè)谥鞒绦蚶飫?chuàng)建了待辦事項(xiàng)站削,怎么才能讓 App Extension 獲取到呢坊萝?由于兩者代碼和數(shù)據(jù)都不互通,所以我們 可以理所當(dāng)然的想到用 App Group 來(lái)解決许起。首先在主程序中創(chuàng)建一個(gè) App Group:

然后在 App Extension 里添加這個(gè) App Group 即可十偶。
這樣,我們就可以用 NSUserDefaults 通過(guò)這個(gè) App Group 交流數(shù)據(jù)了园细。

還記得我說(shuō)過(guò)要拿出所有數(shù)據(jù)的前四條放到今日面板中展示嗎惦积?下面我們就來(lái)實(shí)現(xiàn)這個(gè)功能:


當(dāng)主應(yīng)用的數(shù)據(jù)變化后就調(diào)用這個(gè)方法來(lái)更新快照數(shù)據(jù)。

下面我們主要來(lái)看 Today Extension 怎么實(shí)現(xiàn)猛频,首先看看這兩個(gè)方法:


其中第一個(gè)方法是系統(tǒng)告訴 Extension 需要更新了狮崩,當(dāng)你更新完畢之后通過(guò) block 回調(diào)告訴系統(tǒng)你完成了還有做了什么,通常我們就告訴系統(tǒng)我們更新數(shù)據(jù)了即可(就是給 block 傳 NCUpdateResultNewData 枚舉項(xiàng)作為參數(shù))鹿寻。

其中第二個(gè)方法是返回一個(gè)內(nèi)補(bǔ)大小睦柴,如果不實(shí)現(xiàn),默認(rèn)情況視圖左側(cè)會(huì)有一定的縮進(jìn)毡熏。當(dāng)然坦敌,蘋(píng)果還是希望你不要修改默認(rèn)的內(nèi)補(bǔ)~

然后我們實(shí)現(xiàn)數(shù)據(jù)的讀取:


P.S. 第三行寫(xiě)錯(cuò)了,不要管它
其實(shí)也很簡(jiǎn)單狱窘,就是從 App Group 的配置里拿出前 4 項(xiàng)的快照杜顺,然后更新一下 Table View 即可。這個(gè)方法在 viewDidLoad 或者 widgetPerformUpdateWithCompletionHandler: 中調(diào)用都可以蘸炸。

到這我們看看效果躬络,選中 Today Extension 的那個(gè) Scheme 點(diǎn)擊調(diào)試按鈕,彈出下面的對(duì)話(huà)框:



選擇我們的主程序搭儒,點(diǎn)擊 『Run』洗鸵。

App Extension 調(diào)起主程序并執(zhí)行動(dòng)作

當(dāng)我們的 Todo List 是空的情況下,我們希望在今日面板里展示一個(gè)按鈕仗嗦,點(diǎn)擊后可以快速進(jìn)入創(chuàng)建 Todo 的界面,就像這樣:


由于我們?cè)L問(wèn)不了主程序的代碼甘凭,所以只剩下一條路可以選稀拐,那就是 URL Scheme

首先丹弱,我們給主程序注冊(cè)一個(gè) URL Scheme:


然后響應(yīng)按鈕點(diǎn)擊:


由于 App Extension 訪(fǎng)問(wèn)不了 UIApplication德撬,因此不能用它的 openURL:,但是我們可以用 extensionContext 來(lái)打開(kāi) URL躲胳,用法和效果是一樣的蜓洪。

回到主程序,我們處理 URL 的打開(kāi):


這里我用 Notification 的方式告知指定 View Controller 來(lái)執(zhí)行相應(yīng)動(dòng)作坯苹,當(dāng)然你也可以用你自己喜歡的方式隆檀,這里最復(fù)雜也就是處理路由,現(xiàn)在也有很多方法實(shí)現(xiàn)粹湃,我這里就不深究了恐仑。

下面看看效果(不好意思,圖沒(méi)做好为鳄,不動(dòng)請(qǐng)?jiān)谛麓翱谥写蜷_(kāi)):


好了裳仆,到這我們就基本打通主程序和 App Extension 的相互通信了,是不是也很簡(jiǎn)單呢孤钦?

最后歧斟,一個(gè)小提醒

由于通知中心的界面是一大塊 UIVisualEffectView ,并且具體參數(shù)調(diào)整過(guò)偏形,所以插件的背景色最好保持透明静袖,主要文字顏色最好是白色,次要文字的顏色最好是 lightTextColor壳猜,這樣能適應(yīng)毛玻璃下的 Vibrancy 效果勾徽。

今日面板每個(gè)插件的高度計(jì)算和 UITableView 自適應(yīng)高度的計(jì)算方式一致,如果你沒(méi)有設(shè)置 preferredContentSize,或者把它設(shè)為 CGSizeZero 了喘帚,就表示你想采用自適應(yīng)高度畅姊,那么系統(tǒng)就會(huì)根據(jù)你設(shè)計(jì)的 Auto Layout 來(lái)確定適合的高度慌洪。如果你想這么做的話(huà)俺抽,直接參考 UITableViewCell 在 iOS 8 以后自適應(yīng)高度的方式即可。

完了~希望大家支持莫湘!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倾鲫,一起剝皮案震驚了整個(gè)濱河市粗合,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乌昔,老刑警劉巖隙疚,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異磕道,居然都是意外死亡供屉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)溺蕉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伶丐,“玉大人,你說(shuō)我怎么就攤上這事疯特』┗辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵漓雅,是天一觀(guān)的道長(zhǎng)录别。 經(jīng)常有香客問(wèn)我,道長(zhǎng)故硅,這世上最難降的妖魔是什么庶灿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮吃衅,結(jié)果婚禮上往踢,老公的妹妹穿的比我還像新娘。我一直安慰自己徘层,他們只是感情好峻呕,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著趣效,像睡著了一般瘦癌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跷敬,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天讯私,我揣著相機(jī)與錄音,去河邊找鬼。 笑死斤寇,一個(gè)胖子當(dāng)著我的面吹牛桶癣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播娘锁,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼牙寞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了莫秆?” 一聲冷哼從身側(cè)響起间雀,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镊屎,沒(méi)想到半個(gè)月后惹挟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缝驳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年匪煌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片党巾。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖霜医,靈堂內(nèi)的尸體忽然破棺而出齿拂,到底是詐尸還是另有隱情,我是刑警寧澤肴敛,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布署海,位于F島的核電站,受9級(jí)特大地震影響医男,放射性物質(zhì)發(fā)生泄漏砸狞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一镀梭、第九天 我趴在偏房一處隱蔽的房頂上張望刀森。 院中可真熱鬧,春花似錦报账、人聲如沸研底。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)榜晦。三九已至,卻和暖如春羽圃,著一層夾襖步出監(jiān)牢的瞬間乾胶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留识窿,地道東北人斩郎。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像腕扶,于是被迫代替她去往敵國(guó)和親孽拷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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