about 3 years ago

雖然 Widget 並不是 iOS10 的新功能,但是因為 iOS10 的 UserNotifiction 的研究所以也想要來試著應用 Widget 看看。
App Extension 在 Today 中稱為 Widgets,用來讓使用者立即取得一些資訊。例如:股市價格、天氣狀況、今日行程。使用者會導向頻繁的開啟 Today,並且預期可以看到他們感興趣的資訊。

加入 Widget 的方式一樣也是透過新增 Target(iOS > Application Extension > Today Extension)的方式
並且要先去 developer center 加入一個 App Group,可以讓 Widget 與原本的 APP 做溝通。


- App extension:就是我們的 Widget
- Containing app:是原本開發的 app
- Host app:是呼叫 extension 的 app,舉例來說,如果是一個照片修改的功能 extension,那 host app 可能就是 camera roll。以我們現在的 Widget 討論,那 host app 就是 Today 頁面。
- Shared resource:我們設定了 App Group 讓 extension 可以存取原本 app 的資源空間。

Design

Apple 對於設計方面,提供許多的「建議」,希望你不要因為錯誤的設計,而流失使用者!

  1. Widget 應該保持輕巧迅速
  2. Widget 應該功能單一
  3. Widget 應該不打擾使用者的情況下完成功能
  4. Widget 不要阻塞了 host app

Programming

1. Widget is a ViewController

Widget 其實也是為 ViewController,可以用 App 開發的觀念來進行處理。

2. Layout

在排版的設計方面,寬度是固定的,我們可以針對高度的調整做設計。
可以使用 Autolayout 或是 preferredContentSize。
還有針對邊界的操作,可以使用 NCWidgetProviding 中的 theWidgetMarginInsetsForProposedMarginInsets:

3. interaction

Extension 與 containing APP 的 interaction

  1. 自定的 framework 共享程式碼
  2. 利用 App Group,使用 NSUserDefaults、NSFileCoordinator、NSFilePresenter,甚至是 CoreData 和 SQLite 來共享數據
  3. 自定的 url scheme 來開啟 containing app 與向 app 反饋數據。

4. Some Tips

  1. 在 containing app 中加入一個 applicationWillResignActive 的事件監聽,並在觸發時儲存需要的資料在 UserDefault
  2. 利用設定 preferredContentSize 來調整 widget 的尺寸
  3. 利用 NSExtensionContext 來與 host app 做溝通。最後需要在 containing app 的 target 裡設置適合的 URL Scheme。
    // 在 Widget 中,
    @objc private func buttonPressed(sender: AnyObject!) {
    extensionContext.openURL(NSURL(string: "simpleTimer://finished"), completionHandler: nil)
    }
    // 然後在 AppDelegate.swift 中,處理打開事件,並檢測計時是否完成,然後做出對應:
    func application(application: UIApplication!, openURL url: NSURL!, sourceApplication: String!, annotation: AnyObject!) -> Bool {
    if url.scheme == "simpleTimer" {
        if url.host == "finished" {
            NSNotificationCenter.defaultCenter()
                .postNotificationName(taskDidFinishedInWidgetNotification, object: nil)
        }
        return true
    }
    return false
    }
    
  4. 在 Widget 沒有被出現的時間,系統會定期呼叫,可以進行一些 API 的詢問,來更新widget。

    // 設定 delegate NCWidgetProviding
    @interface TodayViewController () <NCWidgetProviding>
    // some var
    @end
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
    // Perform any setup necessary in order to update the view.
    
    // If an error is encoutered, use NCUpdateResult.Failed
    // If there is no update required, use NCUpdateResult.NoData
    // If there is an update, use NCUpdateResult.NewData
    completionHandler(NCUpdateResult.NewData)
    }
    

相關文章
Apple Dev
human-interface-guidelines
iOS 10
http://www.jianshu.com/p/11a68ae3ef7e
http://cdnnn.07net01.com/2016/09/1674260.html
iOS 8
http://www.takobear.tw/2014/06/28/ios-8-sdk-extension-item/
https://blog.hsin.tw/2015/ios-dev-notification-center-widget-app-today-extension-widget/

← iOS 10 UserNotification Mac版 奇摩注音關閉一點通 →