问题描述
我目前正在尝试将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.
如果要在后台传输数据,则必须根据需要使用 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!
使用 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的核心数据获取请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!