繁体   English   中英

使用WatchConnectivity的核心数据获取请求

[英]Core Data fetch request with WatchConnectivity

我目前正在尝试将CoreData数据从我的iOS应用程序获取到watchOS扩展。 我正在使用WatchConnectivity框架通过sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)获取字典sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)函数。 基本连接工作正常。 iOS应用程序可访问,如果我尝试回复示例字典,则一切正常。

到目前为止,一切都很好,但是当我开始在后台对iOS应用执行提取请求时,Watch App从不接收数据。 一段时间后,我刚收到以下错误消息: Error while requesting data from iPhone: Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedFailureReason=Reply timeout occurred., NSLocalizedDescription=Message reply took too long.} Error while requesting data from iPhone: Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedFailureReason=Reply timeout occurred., NSLocalizedDescription=Message reply took too long.}

如果我在iPhone上打开iOS应用并重新启动Watch App,则回复处理程序将获得结果。 但是,强迫用户在iPhone上积极打开iOS应用程序是没有用的。

有人可以解释为什么会这样吗? 正确的方法是什么? 自watchOS 2起,应用组似乎已过时。
我正在使用Swift 4 btw…

在Apple Watch上:

import WatchConnectivity

class HomeInterfaceController: WKInterfaceController, WCSessionDelegate {

// (…)

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

    session.sendMessage(["request": "persons"],
                         replyHandler: { (response) in
                            print("response: \(response)")
                         },
                         errorHandler: { (error) in
                            print("Error while requesting data from iPhone: \(error)")
    })
}

在iPhone上:

import CoreData
import WatchConnectivity

class ConnectivityHandler: NSObject, WCSessionDelegate {

var personsArray:[Person] = []

// (…)

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {

    // only using the next line is working!
    // replyHandler(["data": "test"])

    if message["request"] as? String == "persons" {
        fetchAllPersons()

        var allPersons: [String] = []
        for person in personsArray {
            allPersons.append(person.name!)
        }

        replyHandler(["names": allPersons])
    }
}

// this seems to be never executed (doesn't matter if it's in an extra function or right in the didReceiveMessage func)
func fetchAllPersons() {

    do {
        // Create fetch request.
        let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()

        // Edit the sort key as appropriate.
        let sortDescriptor = NSSortDescriptor(key: #keyPath(Person.name), ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]

        personsArray = try DatabaseController.getContext().fetch(fetchRequest)
    } catch {
        fatalError("Failed to fetch: \(error)")
    }
}

在研究了这个问题之后,我自己找到了解决方案。 问题是我正在使用sendMessage(_:replyHandler:errorHandler:)协议。 仅当两个应用程序都处于活动状态时,才用于传输数据。

使用sendMessage(_:replyHandler:errorHandler:)sendMessageData(_:replyHandler:errorHandler:)方法将数据传输到可访问的对应对象。 这些方法用于在iOS应用和WatchKit扩展之间进行即时通信。 当前,isReachable属性必须为true才能使这些方法成功。

如果要在后台传输数据,则必须根据需要使用updateApplicationContext(_:)transferUserInfo(_:) 那正是我所需要的!

使用updateApplicationContext(_:)方法将最新状态信息传达给对方。 当对方唤醒时,它可以使用此信息来更新其自身的状态。 例如,支持后台应用刷新的iOS应用可以使用其后台执行时间的一部分来更新相应的Watch应用。 此方法将覆盖以前的数据字典,因此当您的应用程序仅需要最新的数据值时,请使用此方法。

使用transferUserInfo(_:)方法在后台传输数据字典。 您发送的字典排队等待传递给对方,并且在当前应用被暂停或终止时,传输继续进行。

现在,如果iPhone App对方打开了ApplicationContext或UserInfo队列,则可以通过该通道,我可以将数据添加到我的核心数据库中。

可悲的是,大多数WatchConnectivity方法都有时间限制(错误告诉您),并且看来您的CoreData请求占用了太多时间,因此超出了时间限制。 根据此问答 ,您似乎需要在后台进行CoreData查询时采取特定的预防措施,所以这可能是导致问题的原因。

但是,为了获得最佳用户体验,我建议您停止使用CoreDataWatchConnectivity框架,因为后者需要您的iOS应用至少在后台运行,因此使watchOS应用依赖于iOS应用的状态并降低性能watchOS上的用户体验。 我建议您切换到Realm ,因为Realm完全支持watchOS,因此watchOS应用程序可以完全独立于iOS应用程序,从而使用户体验更加流畅,因为用户不必启动iOS应用程序并等待使用WatchConnectivity框架通过BLE进行数据传输。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM