我有一个现有的iOS 9.2和watchOS 2.1应用,它使用sendMessage
和transferUserInfo
将数据从iPhone发送到Apple Watch。如果sendMessage
失败,我使用transferUserInfo
对数据进行排队以便以后投放:
// *** In the iOS app ***
self.session.sendMessage(message, replyHandler: nil) { (error) -> Void in
// If the message failed to send, queue it up for future transfer
self.session.transferUserInfo(message)
}
// *** In the watchOS app ***
func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {
// Handle message here
}
func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
// Handle message here
}
在真实设备上使用watchOS 2.2更改任何代码并在iOS 9.3上运行应用程序(模拟器没有相同的问题),只要手表在范围内,sendMessage
就会向Apple Watch提供数据并且屏幕亮起。这是预期的以及它之前的工作方式。但是,如果屏幕关闭且sendMessage
失败,则transferUserInfo
在屏幕重新开启时不再向Apple Watch提供数据。
为了找到错误的位置,我添加了以下WCSessionDelegate
方法,以查看iOS应用是否无法发送数据:
func session(session: WCSession, didFinishUserInfoTransfer userInfoTransfer: WCSessionUserInfoTransfer, error: NSError?) {
// Called when self.session.transferUserInfo completes
}
调用transferUserInfo
后会调用此方法,但没有返回错误,iOS应用程序似乎表明传输成功。
起初我认为传输数据所花费的时间可能已经增加了,但是在单独离开设备一天之后,数据仍未传输。我现在有点怀疑它与新的多表API有关,也许iOS应用程序需要知道一个特定的手表发送它,虽然我只有一个配对的手表。有没有人对可能发生的变化以及如何正确使用transferUserInfo
?
答案 0 :(得分:3)
我想我现在有这个工作。首先,我必须将新的WCSessionDelegate方法添加到我的iOS应用程序中:
@available(iOS 9.3, *)
func session(session: WCSession, activationDidCompleteWithState activationState: WCSessionActivationState, error: NSError?) {
if activationState == WCSessionActivationState.Activated {
NSLog("Activated")
}
if activationState == WCSessionActivationState.Inactive {
NSLog("Inactive")
}
if activationState == WCSessionActivationState.NotActivated {
NSLog("NotActivated")
}
}
func sessionDidBecomeInactive(session: WCSession) {
NSLog("sessionDidBecomeInactive")
}
func sessionDidDeactivate(session: WCSession) {
NSLog("sessionDidDeactivate")
// Begin the activation process for the new Apple Watch.
self.session.activateSession()
}
与我的watchOS应用程序类似:
@available(watchOSApplicationExtension 2.2, *)
func session(session: WCSession, activationDidCompleteWithState activationState: WCSessionActivationState, error: NSError?) {
if activationState == WCSessionActivationState.Activated {
NSLog("Activated")
}
if activationState == WCSessionActivationState.Inactive {
NSLog("Inactive")
}
if activationState == WCSessionActivationState.NotActivated {
NSLog("NotActivated")
}
}
但是,对于我来说,transferUserInfo仍然不起作用,特别是当Apple Watch的屏幕关闭时。以下是我在iOS 9.2 / watchOS 2.1中的iPhone和Apple Watch之间发送信息的方式:
func tryWatchSendMessage(message: [String : AnyObject]) {
if self.session != nil && self.session.paired && self.session.watchAppInstalled {
self.session.sendMessage(message, replyHandler: nil) { (error) -> Void in
// If the message failed to send, queue it up for future transfer
self.session.transferUserInfo(message)
}
}
}
我曾假设当手表的屏幕关闭时,从iPhone向Apple Watch发送消息导致transferUserInfo失败,因为它位于sendMessage的错误处理程序中。屏幕打开时,sendMessage也按预期工作。但是,即使请求失败,看起来如果手表的屏幕关闭,sendMessage的错误回复处理程序也不总是被调用。这与以前的OS版本不同。这似乎也引起了级联效应,即使条件合适,后续消息也会失败。这让我相信transferUserInfo应该受到责备。
我发现为了让我的消息可靠地通过,我需要检查可达和激活状态。由于我还想继续支持早期的iOS和watchOS版本,我的tryWatchSendMessage方法变成了以下内容:
func tryWatchSendMessage(message: [String : AnyObject]) {
if #available(iOS 9.3, *) {
if self.session != nil && self.session.paired && self.session.watchAppInstalled && self.session.activationState == .Activated {
if self.session.reachable == true {
self.session.sendMessage(message, replyHandler: nil) { (error) -> Void in
// If the message failed to send, queue it up for future transfer
self.session.transferUserInfo(message)
}
} else {
self.session.transferUserInfo(message)
}
}
} else {
// Fallback on earlier versions
if self.session != nil && self.session.paired && self.session.watchAppInstalled {
if self.session.reachable == true {
self.session.sendMessage(message, replyHandler: nil) { (error) -> Void in
// If the message failed to send, queue it up for future transfer
self.session.transferUserInfo(message)
}
} else {
self.session.transferUserInfo(message)
}
}
}
}
进行这些更改似乎解决了我所看到的问题。我有兴趣看看这些是否有助于解决其他人的问题,或者是否仍存在与transferUserInfo无关的问题。
答案 1 :(得分:0)
自上周2.2更新以来,我在沟通工作方面遇到了非常类似的问题 - 但对我来说,我无法获得应用程序上下文或文件转移。
和其他人一样,它在模拟器中工作,但在设备上却没有。
我今天注意到我正在尝试从后台线程发送数据 - 我将所有调用都包裹在dispatch_async(dispatch_get_main_queue())
中,突然一切都在运行。