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

WCSessionDelegatedidReceiveMessage 就是用來接收,可以寫在App 端與 Watch 端,接收完之後也可以依情況回傳 replyreply 的資訊會在 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