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

Posted

技术标签:

【中文标题】如何使用 WatchConnectivity 在我的 iOS 和 Watch 应用程序之间共享信息?【英文标题】:How can I share information between my iOS and Watch apps using WatchConnectivity? 【发布时间】:2017-08-03 15:48:59 【问题描述】:

[免责声明:此问题旨在成为一个wiki问题,以回答有关watchkitwatch-os标签下ios和手表应用程序之间发送数据的常见问题。] p>

我正在开发 Apple Watch 应用,并希望在 iOS 应用和它的 WatchKit extension 之间发送数据。我查看了WatchConnectivity 框架,但并不真正了解其所有方法之间的区别。

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

我应该使用哪个函数向 Watch 发送 UI 更新?

我应该使用哪个函数来发送大数据?

【问题讨论】:

我知道这是一个自我回答的问答对,但已经有很多关于这个主题的问题:How to share data between iPhone and Apple Watch using groups?、WatchOS 2.0 Sharing Data between iOS App and WatchOS App 等等。您应该考虑将您的答案添加到其中之一,而不是创建一个全新的问题。 嗯,你链接的两个问题都很老了,而且都是关于 Objective-C 的。如果您查看我在watchkitwatch-os-3apple-watch 标签中的活动,您会发现我自己已经回答了很多关于这个特定主题的问题并创建了这个问答,因为我觉得没有一般性问题/answer 关于该主题,这是标签中经常被问到的问题。 那么也许您应该编辑您的问题以询问“如何使用 WatchConnectivity 框架在我的 iOS 和 Watch 之间共享信息?”缩小范围。如果您想保持一般性,那么我建议您提出您的问答社区 Wiki。 完成,感谢您的意见。 【参考方案1】:

在撰写此答案时(watchOS3 是当前稳定版本,watchOS4 处于测试阶段),iOS 应用程序与其WatchKit extension 是 WatchConnectivity 框架。 (我直接说,因为这个问答不涉及使用云技术,如 CloudKit 将文件从一台设备上传到互联网并在另一台设备上下载。

首先,让我们讨论WCSession的哪个函数应该用于什么目的。有关代码示例,请向下滚动。

在深入了解细节之前,简要介绍每个功能以及何时使用它们:

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

详细说明

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

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

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

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

更多信息请见App programming guide for watchOS - Sharing Data。

现在一些代码示例:

iOS 应用的AppDelegate 中设置WatchConnectivity

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

【讨论】:

如果您有任何要添加的内容,请随时发表评论或提出修改建议。如果您想询问有关答案的某些部分或更多示例的更多详细信息,请不要犹豫,也可以在 cmets 中告诉我。 不行,在AppDelegate里面试过了,iOS设备上不能调用任何方法,只能发送数据。 @user7684436 请指定“不起作用”。你试图调用哪些你不能调用的方法?如果没有看到您的代码,很难提供帮助。 @DávidPásztor 感谢您的快速回复。 isReachable 在我更新应用程序上下文时为真。我已向 Apple 提交了 TSI - 可能是我的设置有问题,或者它只是无法在模拟器中运行。 Apple 支持人员回复我说在模拟器环境中测试 WatchConnectivity “不够”。

以上是关于如何使用 WatchConnectivity 在我的 iOS 和 Watch 应用程序之间共享信息?的主要内容,如果未能解决你的问题,请参考以下文章

使用 WatchConnectivity 框架的独立手表应用

是否可以在后台使用 WatchConnectivity

有时无法访问配对手表模拟器上的 WatchConnectivity 会话

使用WatchConnectivity获取核心数据获取请求

iPhone 和 Apple Watch 之间的 WatchConnectivity 超时错误

通过 WatchConnectivity 的 sendMessageData 将自定义对象的 NSArray 作为 NSData 传递