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怎么使用安装APP应用程序

关闭辅助视图控制器后,如何继续从 Apple Watch 接收消息/数据

是否可以在实际 Apple Watch 设备上运行 WatchKit 应用程序?

当 Apple Watch 处于后台状态或睡眠模式时,我们如何从 iphone 向 Apple Watch 发送消息?