问题描述
[免责声明:此问题旨在作为一个 wiki 问题来回答有关在 watchkit
和 watch-os 标签.]
我正在开发 Apple Watch 应用程序,并希望在 iOS
应用程序与其 WatchKit 扩展程序
之间发送数据.我查看了 WatchConnectivity
框架,但并没有真正理解其所有方法之间的区别.
I am developing an Apple Watch app and would like to send data between the iOS
app and its WatchKit extension
. I have looked at the WatchConnectivity
framework, but don't really understand the difference between all of its methods.
如果我想即使我的应用程序在后台也能发送数据,我应该使用哪个函数?
Which function should I use if I want to be able to send data even when my apps are in the background?
我应该使用哪个函数向 Watch 发送 UI 更新?
Which function should I use to send UI updates to the Watch?
我应该使用哪个函数来发送大数据?
Which function should I use to send large data?
推荐答案
在撰写此答案时(watchOS3
是当前的稳定版本,watchOS4
处于测试阶段stage),iOS
应用与其 WatchKit 扩展
之间直接通信的唯一选择是 WatchConnectivity 框架.(我说的是直接的,因为这个问答不涉及使用诸如 CloudKit
之类的云技术将文件从一台设备上传到互联网并在另一台设备上下载.)
At the time of writing this answer (watchOS3
is the current stable release and watchOS4
is in beta stage), the only option for direct communication between an iOS
app and its WatchKit extension
is the WatchConnectivity framework. (I said direct, because this Q&A is not concerned with using cloud technologies such as CloudKit
to upload files to the internet from one device and download them on the other one.)
首先,我们来讨论一下WCSession
的哪个函数应该用于什么目的.对于代码示例,请向下滚动.
First, let's discuss which function of WCSession
should be used for what purpose. For the code examples, please scroll down.
在深入研究细节之前,简要介绍每个功能以及何时使用它们:
A quick, one-liner about each function and when to use them before diving deep into details:
updateApplicationContext
:同步应用之间的状态,发送要显示在 UI 上的数据(仅用于发送小块数据)transferUserInfo
:后台发送数据字典transferFile
:后台发送文件sendMessage
:在至少在前台运行的手表应用之间发送即时消息
updateApplicationContext
: synchronise states between the apps, send data to be displayed on the UI (only use it to send small pieces of data)transferUserInfo
: send a dictionary of data in the backgroundtransferFile
: send a file in the backgroundsendMessage
: send an instant message between at least the watch app is running in foreground
updateApplicationContext(_:) 如果你想同步您的应用程序(例如保持 UI 更新或发送状态信息,例如用户登录等).您可以发送数据字典.对该函数的后续调用将替换之前发送的字典,因此对应应用程序仅接收使用 updateApplicationContext
发送的最后一项.系统会尝试在适当的时间调用此函数,以便在需要时接收数据,同时最大限度地减少功耗.因此,当两个应用程序都没有在前台运行时,可以调用该函数,但需要激活 WCSession
才能成功传输.尝试使用 updateApplicationContext
传输大量数据的频繁调用可能会失败,因此对于此用法,请改为调用 transferUserInfo
.
updateApplicationContext(_:) should be used if you want to synchronise your apps (such as keep the UI updated or send state information, like user logged in, etc.). You can send a dictionary of data. Subsequent calls to this function replace the previously sent dictionary, so the counterpart app only receives the last item sent using updateApplicationContext
. The system tries to call this function at an appropriate time for it to receive data by the time it is needed and meanwhile minimising power usage. For this reason, the function can be called when neither app is running in the foreground, but WCSession
needs to be activated for the transfer to succeed. Frequent calls trying to transfer large amount of data using updateApplicationContext
might fail, so for this usage call transferUserInfo
instead.
transferUserInfo(:) 和 transferCurrentComplicationUserInfo 可用于使用高优先级消息将与复杂功能相关的数据发送到 WatchKit 扩展
,并在需要时唤醒 WatchKit 应用程序
.但是请注意,此函数有每日限制,一旦超过,将使用 transferUserInfo
函数传输数据.
transferUserInfo(:) and transferCurrentComplicationUserInfo(:) should be used if you want to send data in the background that needs to be received by the other application. Subsequent calls to this method are queued and all information sent from one app to the other is received. transferCurrentComplicationUserInfo
might be used to send complication-related data to the WatchKit extension
using a high-priority message and waking up the WatchKit app
if needed. However, be aware that this function has a daily limit and once it's exceeded, data is transferred using the transferUserInfo
function.
transferFile(_:metadata:) 在实现和transferUserInfo
的性质,但它接受一个 fileURL 而不是字典作为其输入参数,因此它应该用于将设备本地的文件发送到其对应物.后续呼叫排队.接收到的文件必须在 session(_:didReceive:)
方法中保存到新位置,否则会被删除.
transferFile(_:metadata:) is similar in implementation and nature to transferUserInfo
, but it accepts a fileURL instead of a dictionary as its input parameter and hence it should be used to send files local to the device to its counterpart. Subsequent calls are queued. Received files must be saved to a new location in the session(_:didReceive:)
method, otherwise they are deleted.
sendMessage(:replyHandler:errorHandler:) 和sendMessageData(:replyHandler:errorHandler:) 立即发送数据到对应的应用程序.在调用此方法之前,必须可以访问对应的应用程序.iOS 应用程序始终被认为是可访问的,从 Watch 应用程序调用此方法会根据需要在后台唤醒 iOS 应用程序.Watch 应用程序仅在安装和运行时才被认为是可访问的.传输必须在前台启动.对该方法的后续调用将排队.
sendMessage(:replyHandler:errorHandler:) and sendMessageData(:replyHandler:errorHandler:) send data immediately to a counterpart app. The counterpart app must be reachable before calling this method. The iOS app is always considered reachable, and calling this method from your Watch app wakes up the iOS app in the background as needed. The Watch app is considered reachable only while it is installed and running. The transfer must be initiated in the foreground. Subsequent calls to this method are queued.
有关更多信息,请参阅 watchOS 的应用程序编程指南- 共享数据.
For more information please see App programming guide for watchOS - Sharing Data.
在 iOS
应用的 AppDelegate
中设置 WatchConnectivity
:
Set up WatchConnectivity
in the iOS
app's 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) {}
}
使您的 WatchKit
类符合 WCSessionDelegate
:
extension InterfaceController: WCSessionDelegate {
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {}
}
使用即时通讯功能,sendMessage
:
在 WatchKit 应用程序
中,如果您想立即将信息发送到 iOS
应用程序,请使用此代码.
In the WatchKit app
use this code when you want to send information immediately to the iOS
app.
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)
})
}
}
这篇关于如何使用 WatchConnectivity 在 iOS 和 Watch 应用之间共享信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!