如何使用WatchConnectivity在iOS和Watch应用程序之间共享信息?

Dáv*_*tor 5 ios swift apple-watch watchkit watchconnectivity

[免责声明:此问题旨在成为一个维基问题,以回答有关在iOS watchkitwatch-os标签下观看应用程序之间发送数据的常见问题.]

我正在开发Apple Watch应用程序,并希望在iOS应用程序和它之间发送数据WatchKit extension.我看过这个WatchConnectivity框架,但并没有真正理解它的所有方法之间的区别.

如果我希望即使我的应用程序在后台也能发送数据,我应该使用哪个功能?

我应该使用哪个功能向手表发送UI更新?

我应该使用哪个功能发送大数据?

Dáv*_*tor 12

在撰写此答案时(watchOS3当前稳定版本watchOS4处于测试阶段),应用程序与其 之间直接通信的唯一选择是WatchConnectivity框架.(我直接说,因为这个Q&A并不关心使用云技术,比如从一台设备上传文件到另一台设备上,然后在另一台设备上下载.)iOSWatchKit extensionCloudKit

首先,让我们讨论哪些功能WCSession应该用于什么目的.有关代码示例,请向下滚动.

关于每个功能的快速,单线程以及何时使用它们之前深入细节:

  • updateApplicationContext:同步应用程序之间的状态,发送要在UI上显示的数据(仅用于发送小块数据)
  • transferUserInfo:在后台发送数据字典
  • transferFile:在后台发送文件
  • sendMessage:在至少观看应用程序正在前台运行之间发送即时消息

详细说明

如果要同步应用程序(例如保持UI更新或发送状态信息,如用户登录等),则应使用updateApplicationContext(_ :).您可以发送数据字典.对此函数的后续调用将替换先前发送的字典,因此对应应用程序仅接收使用的最后一个项目updateApplicationContext.系统尝试在适当的时间调用此功能,以便在需要时接收数据,同时最大限度地降低功耗.因此,当应用程序在前台运行时,可以调用该函数,但WCSession需要激活该函数才能使传输成功.尝试传输大量数据的频繁调用updateApplicationContext可能会失败,因此对于此使用调用而言transferUserInfo.

如果要在后台发送需要其他应用程序接收的数据,则应使用transferUserInfo(:)transferCurrentComplicationUserInfo( :).对此方法的后续调用将排队,并且将接收从一个应用程序发送到另一个应用程序的所有信息.transferCurrentComplicationUserInfo可能用于将与复杂性相关的数据发送到WatchKit extension使用高优先级消息并唤醒(WatchKit app如果需要).但是,请注意,此功能具有每日限制,一旦超出,则使用该transferUserInfo功能传输数据.

transferFile(_:metadata :)在实现和性质上类似transferUserInfo,但它接受fileURL而不是字典作为其输入参数,因此它应该用于将设备本地的文件发送到其对应的.后续呼叫排队.接收的文件必须保存到方法中的新位置session(_:didReceive:),否则将被删除.

sendMessage(:replyHandler:errorHandler :)sendMessageData(:replyHandler:errorHandler :)立即将数据发送到对方应用程序.在调用此方法之前,必须可以访问对应的应用程序.iOS应用程序始终被认为是可访问的,并且从您的Watch应用程序调用此方法会根据需要在后台唤醒iOS应用程序.Watch应用程序仅在安装并运行时才被视为可访问.必须在前台启动传输.对此方法的后续调用将排队.

有关更多信息,请参阅watchOS的应用程序编程指南 - 共享数据.

现在一些代码示例:

WatchConnectivityiOS应用程序中设置AppDelegate:

import UIKit
import WatchConnectivity

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    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
    }
}

extension AppDelegate: WCSessionDelegate {

    func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
        print("Message received: ",message)
    }

    //below 3 functions are needed to be able to connect to several Watches
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {}

    func sessionDidDeactivate(_ session: WCSession) {}

    func sessionDidBecomeInactive(_ session: WCSession) {}
}
Run Code Online (Sandbox Code Playgroud)

让你的WatchKit班级符合WCSessionDelegate:

extension InterfaceController: WCSessionDelegate {
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {}
}
Run Code Online (Sandbox Code Playgroud)

使用即时消息功能,sendMessage:

WatchKit app您希望立即向iOS应用程序发送信息时使用此代码.

if WCSession.isSupported() {
    print("WCSession supported")
    let session = WCSession.default()
    session.delegate = self
    session.activate()
    if session.isReachable {
        session.sendMessage(["Instant":"Message"], replyHandler: nil, errorHandler: { error in
            print("Error sending message",error)
        })
    }
}
Run Code Online (Sandbox Code Playgroud)