iPhone无法从AppleWatch接收applicationContext

时间:2019-01-09 08:08:17

标签: ios iphone swift apple-watch wcsession

我创建了一个程序来测试从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的确认信息。

任何帮助将不胜感激,我希望这不是一个愚蠢的错误。

2 个答案:

答案 0 :(得分: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);
        }
    }
}

答案 1 :(得分:0)

imgaussfilt