首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用WatchConnectivity实现核心数据获取请求

用WatchConnectivity实现核心数据获取请求
EN

Stack Overflow用户
提问于 2017-12-09 22:50:39
回答 2查看 1.4K关注 0票数 0

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

到目前为止还不错,但是当我开始在后台的iOS应用程序上执行一个获取请求时,Watch应用程序从未接收过数据。过了一会儿,我得到了一个错误: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.}

如果我在iOS上打开iPhone应用程序并重新启动Watch应用程序,应答处理程序就会得到结果。但是强迫用户在iPhone上主动打开iPhone应用程序是没用的。

有人能解释一下为什么会发生这种事吗?正确的方法是什么?从watchOS 2开始,App组似乎就过时了。

我用的是Swift 4的…

苹果手表上:

代码语言:javascript
复制
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上:

代码语言:javascript
复制
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)")
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-02 16:49:50

在调查了这个问题之后,我自己找到了解决办法。问题是我使用的是sendMessage(_:replyHandler:errorHandler:)协议。这只用于在两个应用程序都处于活动状态时传输数据。

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

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

使用updateApplicationContext(_:)方法将最近的状态信息传递给对应方。当对应方醒来时,它可以使用这些信息来更新自己的状态。例如,支持后台app的iOS应用程序可以使用其部分后台执行时间来更新相应的Watch应用程序。此方法覆盖以前的数据字典,因此,当应用程序只需要最新的数据值时,请使用此方法。 使用transferUserInfo(_:)方法在后台传输数据字典。您发送的字典将排队等待发送给对应方,并且在当前应用程序被挂起或终止时继续传输。

现在,如果iPhone应用程序对口打开,则ApplicationContext或UserInfo队列被传递到槽中,我可以将数据添加到核心数据库中。

票数 3
EN

Stack Overflow用户

发布于 2017-12-10 12:29:27

遗憾的是,大多数WatchConnectivity方法都有时间限制(正如错误告诉您的那样),而且您的CoreData请求似乎花费了太多的时间,因此超过了时间限制。根据这个问答,在后台执行CoreData查询似乎需要采取特定的预防措施,因此这可能是引发问题的原因。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47734060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档