使用WatchConnectivity的核心数据获取请求 [英] Core Data fetch request with WatchConnectivity

查看:82
本文介绍了使用WatchConnectivity的核心数据获取请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently trying to get CoreData data from my iOS app to the watchOS extension. I'm using the WatchConnectivity Framework to get a dictionary via the sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil) function. The basic connection is working fine. The iOS app is reachable and if I try to reply a sample dictionary everything is working.

到目前为止,情况很好,但是当我开始在后台对iOS应用执行提取请求时,Watch App从不接收数据.一段时间后,我刚收到以下错误消息:从iPhone请求数据时出错:Error Domain = WCErrorDomain Code = 7012消息回复花了太长时间.UserInfo = {NSLocalizedFailureReason =发生回复超时.,NSLocalizedDescription =消息回复花了太长时间.}

So far so good, but as I start doing a fetch request on the iOS app in background, the Watch App never receives data. After a while I just get this error: 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应用程序是没有用的.

If I open the iOS app on the iPhone and relaunch the Watch App the reply handler is getting the result. But forcing the user to actively open the iOS app on the iPhone is useless.

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

Can someone explain why this is happen? And what's the right way to do it? App Groups seem to be obsolete since watchOS 2.
I'm using Swift 4 btw…

在Apple Watch上:

On 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 :) 协议.仅当两个应用程序都处于活动状态时,才用于传输数据.

After looking into this problem I found the solution by myself. The problem was that I'm using the sendMessage(_:replyHandler:errorHandler:) protocol. This is only used for transferring data when both apps are active.

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

Use the sendMessage(_:replyHandler:errorHandler:) or sendMessageData(_:replyHandler:errorHandler:) method to transfer data to a reachable counterpart. These methods are intended for immediate communication between your iOS app and WatchKit extension. The isReachable property must currently be true for these methods to succeed.

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

If you want to transfer data in the background you have to use updateApplicationContext(_:) or transferUserInfo(_:) depending on your needs. That's exactly what I needed!

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

Use the updateApplicationContext(_:) method to communicate recent state information to the counterpart. When the counterpart wakes, it can use this information to update its own state. For example, an iOS app that supports Background App Refresh can use part of its background execution time to update the corresponding Watch app. This method overwrites the previous data dictionary, so use this method when your app needs only the most recent data values.

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

Use the transferUserInfo(_:) method to transfer a dictionary of data in the background. The dictionaries you send are queued for delivery to the counterpart and transfers continue when the current app is suspended or terminated.

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

Now if the iPhone App counterpart opens the ApplicationContext or UserInfo queue is passed trough and I can add the data to my core data library.

这篇关于使用WatchConnectivity的核心数据获取请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆