自Apple Watch发布以来,开发人员一直在辩论并提出克服watchOS 1局限性的技术。例如,开发人员一直想知道如何在watchOS应用与其父iOS应用之间可靠地通信,反之亦然。
有许多解决方案可用于解决此问题,例如MMWormhole 。 当然,Apple充分意识到了watchOS 1的局限性,并且watchOS 2的发布解决了watchOS 1的许多局限性。例如,在watchOS 2应用程序及其父级iOS应用程序之间进行通信变得非常简单。 手表连接框架的介绍。
观看连接
Watch Connectivity框架提供了几种在iOS和watchOS 2应用之间进行通信的方式。 使用Watch Connectivity框架,您可以更新对方的信息,发送消息,在后台传输数据,甚至传输文件。 要了解有关框架所有功能的更多信息,建议浏览Apple的 Watch Connectivity框架文档 。
在本教程中,我将向您展示如何在watchOS 2应用程序与其父iOS应用程序之间交换数据,反之亦然。 我们将用来实现此目的的API是sendMessage(_:replyHandler:errorHandler:)
。 通过此方法,开发人员可以在watchOS 2应用程序及其父iOS应用程序之间传输数据。
重要的是要注意,当调用sendMessage(_:replyHandler:errorHandler:)
时,iOS和watchOS 2应用程序会做出不同的响应。 如果watchOS 2应用程序调用了此方法,则操作系统将唤醒iOS应用程序。 但是,如果您将数据从父iOS应用发送到watchOS 2应用,则后者不会唤醒。 这是要记住的重要细节。
先决条件
由于本教程是关于Apple Watch开发的,因此我假设您已经熟悉iOS开发和Swift编程语言。 Watch Connectivity框架仅在watchOS 2上可用,这意味着您需要安装最新版本的Xcode,即Xcode7。可以从Apple的开发人员网站下载Xcode。
1.项目设置
打开Xcode,然后从“ 文件”菜单中选择“ 新建”>“项目... ”。 转到watchOS> Application ,选择带有WatchKit App项目模板的iOS App,然后单击Next 。 将您的应用命名为SendMessageWatch ,将Language设置为Swift ,将Devices设置为iPhone 。 取消选中“ 包括通知场景” ,并确保未选中底部的每个复选框。 单击下一步,然后选择一个位置来保存您的项目。

2.创建用户界面
在此步骤中,我们将为两个应用程序添加标签和按钮。 标签将用于显示我们正在发送的消息,而按钮会将消息发送给对方,iOS应用程序或watchOS 2应用程序。
我们将从iOS应用开始。 打开Main.storyboard并添加标签和按钮。 接下来,为两个用户界面元素创建一个插座,并为按钮添加一个动作。 以下屏幕截图显示了结果。

现在让我们专注于watchOS 2应用程序。 打开Interface.storyboard并在场景中添加标签和按钮。 接下来,在助手编辑器中打开InterfaceController.swift ,为标签和按钮创建一个插座,并为按钮添加一个动作。

有了用户界面,现在就可以放大本教程的主题,将消息从iOS应用发送到watchOS 2应用,反之亦然。
3.使用手表连接框架
使用Watch Connectivity框架交换消息需要使用WCSession
类。 为此,iOS应用程序和watchOS 2应用程序都必须创建并配置WCSession
实例。 配置会话后,我们可以立即进行来回通信。
class InterfaceController: WKInterfaceController,WCSessionDelegate{
var session : WCSession!
...
}
我们通过调用defaultSession
类方法来获得WCSession
类的实例。 这将返回设备的单例会话对象。 然后,我们需要设置会话的委托并激活会话。
在配置和使用WCSession
对象之前,我们需要验证设备上是否支持WCSession
类。 为此,我们在WCSession
类上调用isSupported
类方法。 我们在InterfaceController
类的willActivate
方法中完成所有这些操作。 请注意,如果会话的委托为nil
,那么activateSession
将引发异常。 换句话说,以下语句的顺序很重要。
override func willActivate() {
super.willActivate()
if (WCSession.isSupported()) {
session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
watchOS 2应用程序现在可以发送和接收消息。 激活会话后,我们只需要调用sendMessage(_:replyHandler:errorHandler:)
方法即可发送消息。 第一个参数必须是[String : AnyObject]
类型的字典,并且不应为nil
。
replyHandler
是一个接受相同类型字典的闭包。 这本字典是对方的回应。 errorHandler
也是一个闭包,如果您不需要捕获任何错误,则可以为nil
。
如果我们点击Apple Watch上的发送按钮,它将立即发送一条Hello iPhone消息,并且iPhone会回复一条Hello Watch消息。 按下iPhone上的“发送”按钮后,它将发送一个问题嗨,手表,你能和我说话吗? 然后Apple Watch会回答“ 是” 。
这就是在InterfaceController.swift中 sendMessage
方法的实现应该是什么样子。
@IBAction func sendMessage() {
let messageToSend = ["Value":"Hello iPhone"]
session.sendMessage(messageToSend, replyHandler: { replyMessage in
//handle and present the message on screen
let value = replyMessage["Value"] as? String
self.messageLabel.setText(value)
}, errorHandler: {error in
// catch any errors here
print(error)
})
}
要在iOS设备上处理消息,我们需要实现WCSessionDelegate
协议的session(_:didReceiveMessage:)
WCSessionDelegate
session(_:didReceiveMessage:)
委托方法,当对方收到消息时会调用该方法。 这是InterfaceController .swift中的实现形式 。
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
//handle received message
let value = message["Value"] as? String
//use this to present immediately on the screen
dispatch_async(dispatch_get_main_queue()) {
self.messageLabel.setText(value)
}
//send a reply
replyHandler(["Value":"Yes"])
}
对于iOS应用程序,这两种方法的实现看起来非常相似。 通过以上实现,请尝试实现sendMessage
和session(_:didReceiveMessage:replyHandler:)
方法。 这就是ViewController
类的实现。
import UIKit
import WatchConnectivity
class ViewController: UIViewController, WCSessionDelegate {
var session: WCSession!
@IBOutlet var messageLabel: UILabel!
@IBOutlet var sendButton: UIButton!
@IBAction func sendMessage(sender: AnyObject) {
//Send Message to WatchKit
let messageToSend = ["Value":"Hi watch, can you talk to me?"]
session.sendMessage(messageToSend, replyHandler: { replyMessage in
//handle the reply
let value = replyMessage["Value"] as? String
//use dispatch_asynch to present immediately on screen
dispatch_async(dispatch_get_main_queue()) {
self.messageLabel.text = value
}
}, errorHandler: {error in
// catch any errors here
print(error)
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (WCSession.isSupported()) {
session = WCSession.defaultSession()
session.delegate = self;
session.activateSession()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Swift
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
//handle received message
let value = message["Value"] as? String
dispatch_async(dispatch_get_main_queue()) {
self.messageLabel.text = value
}
//send a reply
replyHandler(["Value":"Hello Watch"])
}
}
生成并运行应用程序以查看最终结果。 当您点击Apple Watch上的按钮时,在运行iOS应用程序的配对iPhone上应出现一条消息。 当您点击iOS应用程序的按钮时,将在运行watchOS 2应用程序的Apple Watch上显示一条消息。

4.探索WCSessionDelegate
协议
我们实现的接收消息的委托方法具有一个更简单的同级session(_:didReceiveMessage:)
。 在没有回复处理程序的情况下调用sendMessage(_:replyHandler:errorHandler:)
将调用此方法。 这仅表示发送消息的应用程序不希望响应。
除了向相应对象发送字典外,还可以使用sendMessageData(_:replyHandler:errorHandler:)
方法发送NSData
对象。 对方通过接收该消息session(_:didReceiveMessageData:)
和session(_:didReceiveMessageData:replyHandler:)
所述的委托方法WCSessionDelegate
协议。
结论
如果您需要立即与对方进行通信,那么Watch Connectivity框架是watchOS 2上的最佳选择。消息按照发送时的顺序进行排队和传递。
Watch Connectivity框架提供的功能远远超出本教程中介绍的内容。 在以后的教程中,我们将更深入地研究这个新框架,以进一步探索其功能。
翻译自: https://code.tutsplus.com/tutorials/watchos-2-communicating-with-a-counterpart--cms-24372