代码之家  ›  专栏  ›  技术社区  ›  chriscrutt

iPhone未从AppleWatch接收ApplicationContext

  •  0
  • chriscrutt  · 技术社区  · 7 年前

    我已经创建了一个程序来测试从iPhone和AppleWatch来回发送数据,反之亦然。我已经设置好了,所以AppleWatch上有一个按钮,iPhone上有一个按钮。当按下iPhone One时,它将发送数据,并将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。

    任何帮助都会非常感谢,我希望这不是一个愚蠢的错误。

    2 回复  |  直到 7 年前
        1
  •  1
  •   D. Mika    7 年前

    我想 updateApplicationContext 不是满足您需求的正确方法。 来自文档: 当机会出现时,系统发送上下文数据,目的是在对方唤醒时让数据准备好使用。 如果您想在两个应用程序都在前台时来回发送数据 sendMessage 应该工作。

    最后,您可能需要实现这两种方法的组合。我建议阅读以下文件: https://developer.apple.com/documentation/watchconnectivity/wcsession

    编辑:

    为了更清楚地说明“最终你可能需要实现两种方法的组合”,我从我的一个应用程序中添加了一些示例代码。

    方法 _sendData 尝试通过发送当前数据 sendMessageData ,如果可以到达手表。如果没有,它会更新应用程序上下文,使数据在Watch应用程序启动时可用。

    - (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);
            }
        }
    }
    
        2
  •  0
  •   Manish_Nainwal    7 年前
    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] = [:]) {
    }