iPhone 未从 Apple Watch 接收应用程序上下文
Posted
技术标签:
【中文标题】iPhone 未从 Apple Watch 接收应用程序上下文【英文标题】:iPhone not receiving applicationContext from AppleWatch 【发布时间】:2019-01-09 08:08:16 【问题描述】:我创建了一个程序来测试从 iPhone 和 AppleWatch 来回发送数据,反之亦然。我已经设置好了,AppleWatch 上有一个按钮,iPhone 上有一个按钮。当 iPhone 被按下时,它将发送数据并将 AppleWatch 上的按钮重命名为该数据字符串。
然后,我为 iPhone 实现了 AppleWatch 的相同代码,但由于某种原因,iPhone 似乎没有接收到数据。这是 iPhone 的代码:
// ViewController.swift
import UIKit
import Foundation
import WatchConnectivity
class WatchManager: UIViewController, WCSessionDelegate
var watchSession: WCSession?
didSet
if let session = watchSession
session.delegate = self
session.activate()
override func viewDidLoad()
super.viewDidLoad()
watchSession = WCSession.default
private func sendDict(_ dict: [String: Any])
do
try self.watchSession?.updateApplicationContext(dict)
catch
print("Error sending dictionary \(dict) to Apple Watch!")
@IBOutlet weak var transferButton: UIButton!
@IBAction func dataTransfer(_ sender: Any)
sendDict(["DataKey": UUID().uuidString])
print("sent")
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?)
print("Session activation did complete")
public func sessionDidBecomeInactive(_ session: WCSession)
print("session did become inactive")
public func sessionDidDeactivate(_ session: WCSession)
print("session did deactivate")
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any])
print("phone received app context: ", applicationContext)
if let temperature = applicationContext["DataKey"] as? String
self.transferButton.setTitle(temperature, for: .normal)
和 AppleWatch:
// InterfaceController.swift
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController
var watchSession: WCSession?
didSet
if let session = watchSession
session.delegate = self
session.activate()
@IBOutlet weak var temperatureLabel: WKInterfaceButton!
private func sendDict(_ dict: [String: Any])
do
try self.watchSession?.updateApplicationContext(dict)
catch
print("Error sending dictionary \(dict) to iPhone!")
@IBAction func button()
let urg = ["DataKey":UUID().uuidString]
sendDict(urg)
print("watch sent app context \(urg)")
extension InterfaceController: WCSessionDelegate
#if os(ios)
public func sessionDidBecomeInactive(_ session: WCSession)
public func sessionDidDeactivate(_ session: WCSession)
session.activate()
#endif
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?)
print("Session activation did complete")
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any])
print("watch received app context: ", applicationContext)
if let temperature = applicationContext["DataKey"] as? String
self.temperatureLabel.setTitle(temperature)
override func willActivate()
// This method is called when watch view controller is about to be visible to user
super.willActivate()
watchSession = WCSession.default
override func didDeactivate()
// This method is called when watch view controller is no longer visible
super.didDeactivate()
我尝试更改键的名称(没有用),我做到了,所以数据值总是在变化(UUID().uuidString)并保持不变。我尝试过的其他事情包括创建一个标签并尝试重命名该标签而不是失败的按钮,最后不是重命名按钮,而是发送一些确认它已将数据发送回失败的 Apple Watch。
任何帮助将不胜感激,我希望这不是一个愚蠢的错误。
【问题讨论】:
【参考方案1】:我认为updateApplicationContext
不是满足您需求的正确方法。
从文档:
系统会在机会出现时发送上下文数据,目的是在对方醒来时准备好使用数据。
如果您想在两个应用程序都在前台时来回发送数据,sendMessage
应该可以工作。
最后,您可能需要实现这两种方法的组合。我建议阅读以下文档:https://developer.apple.com/documentation/watchconnectivity/wcsession
编辑:
为了更清楚地说明“最终您可能需要实现两种方法的组合”,我从我的一个应用中添加了一些示例代码。
如果手表可访问,_sendData
方法会尝试通过sendMessageData
发送当前数据。如果不是,它会更新应用程序上下文,以便在手表应用程序启动时提供一些可用的数据。
- (void)_sendCurrentData
if ([WCSession defaultSession].isPaired && [WCSession defaultSession].isWatchAppInstalled)
if ([WCSession defaultSession].isReachable)
// Send data to watch
[[WCSession defaultSession] sendMessageData:self.currentData
replyHandler:nil
errorHandler:^(NSError * _Nonnull error)
[self _updateApplicationContext];
];
else
[self _updateApplicationContext];
- (void)_updateApplicationContext
if ([WCSession defaultSession].isPaired && [WCSession defaultSession].isWatchAppInstalled)
NSError* error = nil;
[[WCSession defaultSession] updateApplicationContext:@@"data": self.currentData
error:&error];
if (error != nil)
NSLog(@"error while updating application context: %@", error.localizedDescription);
【讨论】:
在与延迟和userinfo
的挫败作斗争之后,我决定尝试sendMessage
,并几乎为它传输数据的速度而哭泣。谢谢。【参考方案2】:
use self.watchSession?.transferUserInfo(dict) instead of self.watchSession?.updateApplicationContext(dict)
you'll got a call back in:
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:])
【讨论】:
这只会在我单击 iPhone 按钮后更新 iPhone 按钮文本。因此,我单击手表按钮,并且在单击 iPhone 按钮之前,iPhone 按钮文本不会改变。这是为什么呢? 我通过在self.transferButton.setTitle(temperature, for: .normal)
周围添加 DispatchQueue.main.async
来修复它以上是关于iPhone 未从 Apple Watch 接收应用程序上下文的主要内容,如果未能解决你的问题,请参考以下文章
当 iPhone 不在附近时,使用 Swift 将数据从 Apple Watch 发送到 iPhone
如何从 Apple Watch 获取传感器数据到 iPhone?
关闭辅助视图控制器后,如何继续从 Apple Watch 接收消息/数据