iOS extension 的出現,友善了使用者檢視應用的服務,比如使用者可以在 Today 的 widgets 中檢視應用的簡略資訊,然後點選進入相關的應用界面。

添加 Widget 流程
1、添加 Today Extension
2、繪制 UI
3、調起 app
4 、資料共享
在 Xcode菜單 => File => New => Target.. => 中選擇 Today Extension
建立 Today Extension 時會預設建立 MainInterface.storyboard,可以在裡面繪制顯示的 Widget 内容,也可以使用代碼繪制 UI。
設定 Widget 展示視圖的大小。關于 Widget 的背景色,以及具體展示的内容大家按需繪制。
在 iOS8 - iOS9 中運作程式後,會發現一個問題:繪制的内容與左側邊界有一定距離(約 30px)。如何解決這個問題呢,NCWidgetProviding 協定給出了解決方案。iOS10 中不存在這個問題。
因為 extension 和 containing app 是兩個完全獨立的程序,是以它們之間不能直接通信(不能像應用内部點選按鈕,跳轉到指定頁面)。為了實作 Widget 調起 app,這裡通過 openURL 的方式來啟動 containing app。
在 containing app 中設定 URL Schemes
在 extension 的 ViewController 中添加如下代碼。
通過 App Groups 提供的同一 group 内 app 共同讀寫區域,可以用 NSUserDefaults 和 NSFileManager 兩種方式實作 extension 和 containing app 之間的資料共享。
1) 通過 NSUserDefaults 共享資料
儲存資料
讀取資料
2) 通過 NSFileManager 共享資料
1、Widget 中展開、折疊
iOS10 在 NSExtensionContext 中,新添了 widgetLargestAvailableDisplayMode 屬性,來确認目前 Widget 是展開還是折疊狀态。是以,先在 viewWillAppear 中設定 Widget 的 mode 為展開。
然後,就是展開和折疊的處理了。在 NCWidgetProviding 協定中,新添了這個方法 widgetActiveDisplayModeDidChange。
2、啟動 app 後,第一次顯示的是折疊,而不是展開 ?
這個問題,歸咎于 preferredContentSize 的設定,确認 Widget 的 mode 之前,不要設定這個值。在 widgetActiveDisplayModeDidChange 中設定展開或折疊狀态下 Widget 的高度,iOS10 環境下在這裡設定高度也就足夠了。
3、為什麼有時展開或折疊 "失靈" 了,沒有對應的展開或折疊呢 ?
這個問題的前提,肯定是你展開、折疊對應的 Widget 高度不一樣,隻是看到了右上角按鈕内容改變,但高度卻沒有變。
這個問題的原因在于,點選展開、折疊按鈕修改了 Widget 的 mode 之後,卻沒有設定對應的高度 preferredContentSize。怎麼辦呢?mode 改變後,設定對應狀态下的高度即可。
真機調試 Widget,牽扯到配置 group。首先我們的宿主 app id 為 com.qianqianstudio.TodayWidget, Today widget 插件的 bundle id 為 com.qianqianstudio.TodayWidget.Widget 這裡我們需要注意,widget 的 bundle id 必須以宿主 bundle id 作為字首。然後它倆之間建立的 group id 為 group.qianqianstudio.freeInHouse(可以取任意名)。
<a href="https://developer.apple.com">開發者證書配置</a>
Identifiers => App Groups 裡添加一個 app group id 為:group.qianqianstudio.freeInHouse
建立 app id。建立的時候選擇 Explict App ID,App Services 裡面勾選上 App Groups
主 app
widget
配置 provisioning profile(這裡不再贅述 certificate 的生成步驟,添加 device 等),此時因為選擇了勾選了 App Groups 這個 service 的 app id,是以可以看到 enabled services 那裡有此項。