如何在后台共享数据——Swift中如何在Apple Watch和iPhone之间共享数据

3
我是一位有用的助手,可以为您进行文本翻译。
我有一个功能应用程序,用于在iPhone和Watch之间共享数据(共享文本),我希望即使手表处于后台状态,它也能正常工作(当手表处于后台时,从iPhone向手表发送数据)。我阅读了很多关于如何实现这一点的文章,但似乎没有适合我的应用程序。请添加代码以使应用程序按照我之前所说的方式工作。或者给我一些适合这个应用程序的资源。谢谢!
iPhone代码:
    import UIKit
    import WatchConnectivity
    class ViewController: UIViewController, WCSessionDelegate {

    @IBOutlet weak var iPhoneLabel: UILabel!
    var session : WCSession!;

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

    }

    func sessionDidBecomeInactive(_ session: WCSession) {

    }

    func sessionDidDeactivate(_ session: WCSession) {

    }

    func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
        let msg = message["b"] as? String;
        self.iPhoneLabel.text = msg;

    }



    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        if(WCSession.isSupported()){
            self.session = WCSession.default;
            self.session.delegate = self;
            self.session.activate();
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func sendMessage(_ sender: Any) {
         session.sendMessage(["a" : "Hello"], replyHandler: nil, errorHandler: nil);
    }
}

观察代码:

    import WatchKit
    import Foundation
    import WatchConnectivity
    import UIKit

    class InterfaceController: WKInterfaceController, WCSessionDelegate {

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

    }


    @IBOutlet var WatchLabel: WKInterfaceLabel!
    var session: WCSession!;

    func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
        //self.label.setText(message["a"]! as? String)


        let msg = message["a"] as? String;
        WatchLabel.setText(msg);
        sendMessage();



    }

    func sendMessage(){
         session.sendMessage(["b":"goodbye"], replyHandler: nil, errorHandler: nil);
    }


    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        // Configure interface objects here.
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()

        if(WCSession.isSupported()){
            self.session = WCSession.default;
            self.session.delegate = self;
            self.session.activate();
        }
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }
   }

我将方法session.sendMessage()更改为session.updateApplicationContext()后,它只能工作一次。有什么建议吗?

iPhone的代码:

import UIKit

import WatchConnectivity


class ViewController: UIViewController, WCSessionDelegate {


@IBOutlet weak var iPhoneLabel: UILabel!

var session : WCSession!;



func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}

func sessionDidBecomeInactive(_ session: WCSession) {
}


 func sessionDidDeactivate(_ session: WCSession) {
}




 func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {



let msg = applicationContext["b"] as? String

//Use this to update the UI instantaneously (otherwise, takes a little while)
DispatchQueue.main.async() {
    self.iPhoneLabel.text = msg;
}

}



override func viewDidLoad() {
super.viewDidLoad()


if(WCSession.isSupported()){
    self.session = WCSession.default;
    self.session.delegate = self;
    self.session.activate();
}
}


override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}


@IBAction func sendMessage(_ sender: Any) {



let applicationDict = ["a":"Hello"];
do {
    try session.updateApplicationContext(applicationDict)
} catch {
    print("error")
}
}

}

代码观察:
import WatchKit

import Foundation

import WatchConnectivity

import UIKit


class InterfaceController: WKInterfaceController, WCSessionDelegate {


func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

}


@IBOutlet var WatchLabel: WKInterfaceLabel!
var session: WCSession!;



func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
    print("Watch message received")

    let msg = applicationContext["a"] as? String
    DispatchQueue.main.async() {
        self.WatchLabel.setText(msg);
    }
    sendMessage();
}

func sendMessage(){


    print("Watch send message");
    let applicationDict = ["b":"goodbye"];
    do {
        try session.updateApplicationContext(applicationDict)
    } catch {
        print("error")
    }
}


override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    // Configure interface objects here.
}

override func willActivate() {
    // This method is called when watch view controller is about to be visible to user
    super.willActivate()

    if(WCSession.isSupported()){
        self.session = WCSession.default;
        self.session.delegate = self;
        self.session.activate();
    }
}

override func didDeactivate() {
    // This method is called when watch view controller is no longer visible
    super.didDeactivate()
}

}
1个回答

3
简而言之,您应该使用updateApplicationContext方法而不是sendMessage方法,以便即使Watch应用程序在后台运行,也能从iPhone应用程序发送数据。如需更多信息,请继续阅读。
如果查看 documentation,它指出调用session.sendMessage方法只会唤醒Watch应用程序,而不会唤醒Watch应用程序在后台运行时。

从 WatchKit 扩展中调用此方法时,如果它处于活动状态并正在运行,则会唤醒相应的 iOS 应用并使其可访问。从 iOS 应用中调用此方法不会唤醒相应的 WatchKit 扩展。如果调用此方法且对应项无法访问(或在消息传递之前变为不可访问),则 errorHandler 块将执行相应的错误。

它还指出此功能仅在isReachabletrue时才有效。
使用 sendMessage(:replyHandler:errorHandler:) 或 sendMessageData(:replyHandler:errorHandler:) 方法向可达的对等端传输数据。这些方法旨在在您的iOS应用程序和WatchKit扩展之间进行即时通信。这些方法要成功,isReachable属性必须当前为true。
对于发送用于更新UI的数据,您应该使用updateApplicationContext(_: )方法,使用该方法可以
系统会在机会出现时发送上下文数据,目的是让数据在对等方醒来时准备好使用。
为了使此方法起作用,session只需要被激活,而不需要可达。

你是对的,但是我使用了这种方法之后,它没有执行任何操作。有什么建议吗?我会在下面发布代码。 - user8403747
@Victor.D 请不要将此作为答案发布,而是编辑您的原始问题。'updateApplicationContext' 是否抛出错误?您是在模拟器上还是真实设备上进行测试? - Dávid Pásztor
我认为编辑帖子可能不太好,因为可能有其他解决方案可以应用于原始代码。我没有收到任何错误消息,并且正在模拟器上进行测试。我已经制作了另外两个使用updateApplicationContext的应用程序,但它们都无法正常工作。(App1: https://kristina.io/watchos-2-tutorial-using-application-context-to-transfer-data-watch-connectivity-2/ App2: http://www.codingexplorer.com/watch-connectivity-swift-application-context/)。 - user8403747
没问题,这就是SO的工作方式。如果您对原始代码进行了一些更改,但仍然出现错误,则应在原始问题中编辑代码,绝不要将其发布为答案。当其他人寻找相同的问题时,他们希望在答案中看到可行的代码。 - Dávid Pásztor
1
下次我会做得更好。 - user8403747
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接