Edited at

watchOS Watch Connectivity

More than 1 year has passed since last update.


はじめに

この記事は、岩手県立大学アドベントカレンダー2016 10日目の記事です。

watchOSアプリを改修するにあたりwatchOS 1で利用可能だったフレームワークのいくつかがwatchOS 2やwatchOS 3で利用不可能だということに気づきました。

例えば、SystemConfiguration.frameworkやCFNetwork.frameworkなどです。

これらのフレームワークの機能を使う方法を考えました。


Watch Connectivity

Watch Connectivity framework(WatchConnectivity.framework)は、iPhone(iOSアプリ)とApple Watch(watchOSアプリ)の間でデータの送受信を提供します。

データの送受信をOSが決めるBackground transfersとデータをすぐに転送するInteractive messagingがあります。


実装

今回は、Interactive messagingを実装します。

実行環境は以下のとおりです。


  • Xcode 8.1

  • iPhone 7(iOS 10.1.1)

  • Apple Watch(watchOS 3.1)

watchOS側の実装は以下のようになります。


InterfaceController.swift

import WatchKit

import Foundation
import WatchConnectivity

class InterfaceController: WKInterfaceController, WCSessionDelegate {
override func awake(withContext context: Any?) {
super.awake(withContext: context)
}

override func willActivate() {
super.willActivate()

if WCSession.isSupported() {
// Watch Connectivityをサポートしているとき
let session = WCSession.default()
session.delegate = self
session.activate()
if session.isReachable {
// iPhoneと通信可能のとき
session.sendMessage([:], replyHandler: {(replay) -> Void in

let buttonAction = WKAlertAction(title:"OK", style: .default) { () -> Void in
}
self.presentAlert(withTitle: "タイトル", message: replay.description, preferredStyle: .alert, actions: [buttonAction])
}){(error) -> Void in
print(error)
}
}
}
}

override func didDeactivate() {
super.didDeactivate()
}

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

}


次にiOS側の実装です。


AppDelegate.swif

import UIKit

import WatchConnectivity

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate {

@available(iOS 9.3, *)
public func sessionDidDeactivate(_ session: WCSession) {

}

@available(iOS 9.3, *)
public func sessionDidBecomeInactive(_ session: WCSession) {

}

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if WCSession.isSupported() {
let session = WCSession.default()
session.delegate = self
session.activate()
}
return true
}

func applicationWillResignActive(_ application: UIApplication) {
}

func applicationDidEnterBackground(_ application: UIApplication) {
}

func applicationWillEnterForeground(_ application: UIApplication) {
}

func applicationDidBecomeActive(_ application: UIApplication) {
}

func applicationWillTerminate(_ application: UIApplication) {
}

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
if session.isReachable {
// Apple Watchに結果を送信する
replyHandler(["Hello":"World"])
}
}

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



実行結果

watchOSアプリを起動します。

アラートが表示されデータが送受信できたことがわかります。

このときiOSアプリは起動していなくてもデータの送受信可能です。

この仕組みを使えばwatchOSで用意されていないフレームワークの機能をiOSアプリで処理してwatchOSアプリに結果を渡すことができそうです。