Home 寫程式從零開始寫 WatchOS(2) – Watch Connectivity

從零開始寫 WatchOS(2) – Watch Connectivity

by 艾普利
Photo by Raagesh C on Unsplash

Photo by Raagesh C on Unsplash

上篇利用了 Apple 的官方教學簡單了解要怎麼建立一個 Watch App,不過在教學裡的Watch 資料是可以獨立取得的,在多數的情況下,都是要從 iOS App 中取得資料,需要與 iOS App 溝通才行,而 Watch Connectivity 就是用來與WatchOS 溝通的Framework

本篇使用 Xcode 14.3 & SwiftUI


Watch Connectivity

它是負責Watch 與 App 之前的溝通,有提供幾種資料傳遞,也有提供背景傳遞方式,本篇內容是利用 Watch Connectivity 中的SendMessage 來進行簡單的資料傳遞,這種方式是必須在手錶不是在背景的情況下才可以進行資料傳送,算是比較即時的資料傳送方式

WatchConnectivity 就如它的名字是負責用來做為 WatchOS App 與 iOS App 之間的溝通,因此在 WatchOS 端與 iOS 端都需要寫相同的function 用來確認連結與傳遞資料,就如圖片所示

WCSection

WCSession 無論那種傳送方式都是使用這個 Class ,在 iOS App 與 WatchOS App 都要寫上 WCSession,它會進行檢查與傳送工作

import WatchConnectivity
if WCSession.isSupported() {
    let session = WCSession.defaultSession()
    session.delegate = self
    session.activateSession()
}
  • 需要先使用 WCSession.isSupported()確認是否有支援互相傳送資料
  • 建立一個Session基本上沒有什麼特別需求的話就直接使用Default 的就好
  • 設定好 Delegate
  • 最後就是 Activate session

WCSessionDelegate

這個Delegate 中有用來接收雙方資料的function 也有確認是否連線成功的 function,若使用 SwiftUI 來撰寫,接收會影響UI 更新的參數時,記得要使用 @Published var 來接,不然UI 就不會更新了

下面三個function 在 App 端一定要實作的,Watch 端的話只需要實作第一個,簡單說一下這三個的用途

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
    
func sessionDidBecomeInactive(_ session: WCSession) {
}

func sessionDidDeactivate(_ session: WCSession) {
}
  • activationDidCompleteWith,就是當呼叫完 activateSession 之後會觸發
  • sessionDidBecomeInactive,停止連線的時候會觸發
  • sessionDidDeactivate,當所有資料傳送完成且停止連線的時候會觸發

本篇中在這三個時機點並沒有要特別處理什麼事情,所以並不會在這三個function 裡寫東西。

Send Message

用 Message 的方式傳送的 Data 是 Dictionary ,Key 可以自定,使用 Dictionary 就可以使用Decodable 的讓它變成 Data Object 這樣之後會比較好處理

func sendHiToWatch() {
    guard let wcSection = section, wcSection.isReachable else {
         return
    }
    
    let hiDic = ["Say": "Hi, Watch"]
    wcSection.sendMessage(hiDic) { result in
        print("Result : \(result)")
    }
}

在 sendHiToWatch 裡簡單建立一了個 Dictionary ,Key是 “Say”,Value是 “Hi, Watch”,因為 Message 的傳送方式 Watch App 必需要在前景,因此使用 isReachable 來確認是否可以傳送Message。

再來就是呼叫 sendMessage 這個func 將想要的資料傳送出去

Receive Message

在 WCSessionDelegate 中 didReceiveMessage 就是用來接收,可以寫在App 端與 Watch 端,接收完之後也可以依情況回傳 reply ,reply 的資訊會在 sendMessage 的Result中。

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
        
     let hiMessage = message["Say"] as! String
        
     DispatchQueue.main.async {
         self.appMessage = hiMessage
     }
        
     let reply = ["Get": "Good"]
     replyHandler(reply)
}

之所以使用 DispatchQueue.main.async{} 是因為 appMessage 這個參數是要用來更新UI 的,更新UI 的參數一定要在main thread 上才行喔。

Run

寫完之後就可以跑跑看啦~ 若是要用Simulator 的話,記得要下載Watch Simulator 並且與 iPhone Simulator 配對,此外還有一些設定要做,不然就會發現App 都可以跑起來但是就是無法傳送資料

下一篇會整理一下我在這個中間遇到的一些問題,並說明要 Simulator要如何配對

最後祝大家 Coding 愉快!!

Reference

Video

There and back again: Data transfer on Apple Watch

Introducing Watch Connectivity

Document

Watch Connectivity

You may also like