获取 AppleWatch 的 GooglePlaces API(以及一般的异步调用)数据(使用 WCSession)
Getting GooglePlaces API (and asynchronous calls in general) data for AppleWatch (using WCSession)
所以 - 在玩了很多次之后 - 我找到了一种让它工作的方法,但我有一个东西我没有想出如何绕过(让我发疯..)。
我有一个手表应用程序需要来自 GooglePlaces 的数据(iOS 尚无界面...)。所以 - 我使用 WCSession,并使用 phone,使用 sendMessage
,通过 phone 查询 GooglePlaces,将附近的地点返回到手表。
首先,GooglePlaces currentPlace
函数似乎是在调用它的同一线程上调用的(通过排队等待稍后使用)——这是一个问题,因为它被安排在程序关闭后的时间(因为函数 didReceiveMessage
在调用之前就已经退出了)。因此,我没有 运行 将它放在主队列上,而是启动一个线程并 运行 上面的代码....
它的一个问题是 replyHandler
必须在 session:didReceiveMessage
完成执行之前调用(否则如果应用程序处于后台模式,进程将被终止)。
所以我为绕过这个问题而构建的代码看起来像这样(注意我有一个嵌套的 cloudKit 代码......):
let queue = OperationQueue();
var finishedRunning = false;
queue.addOperation{
sleep(1);
self.placesClient?.currentPlace(callback: {
(placeLikelihoodList: GMSPlaceLikelihoodList?, error: Error?) -> () in
if let err = error {
retVal.removeAll();
retVal["error"] = err.localizedDescription;
finishedRunning = true;
return;
}
let predicate = NSPredicate(format: "selected = 1");
let query = CKQuery(recordType: "someInfo", predicate: predicate);
let privDb = CKContainer.default().privateCloudDatabase;
privDb.perform(query, inZoneWith: nil, completionHandler: {records, error in
if let err = error {
retVal.removeAll();
retVal["error"] = err.localizedDescription;
finishedRunning = true;
return;
}
retVal["completed"] = 1;
finishedRunning = true;
});
});
}
while !finishedRunning{
sleep(1);
}
marker = true;
replyHandler(retVal);
那些仔细阅读代码的人注意到我在上面添加了一个 sleep(1);
命令...在开始队列后立即。
我不清楚为什么,但是如果没有这个睡眠调用,就不会调用 GooglePlaces 回调!!
我真的很想删除这个特定的调用..
有人知道为什么会这样吗?
如何绕过它?
(P.S。我不确定是否需要锁来保护 finishedRunning
.. 因为它有效,我认为 none 是必要的。
P.S。 #2 - 我知道它是 "dirty",但没有其他方法可以绕过它......因为我想要手表上的这些数据,我放弃了优雅......
谢谢!!
根据我的经验,sendMessage
的 replayHandler
不必在委托方法 returns 之前调用,但如果您确实希望保持该行为,您可以摆脱至少有一个 `sleep(1) 所以有:
<...>
queue.waitUntilAllOperationsAreFinished()
marker = true;
replyHandler(retVal);
我对 GooglePlaces 一无所知 API 所以我不知道为什么需要再睡一觉。综上所述,因为我不相信必须在委托方法 returns 之前调用 replayHandler
的基本假设,所以切换到执行此任务的更异步的方式可能会更好。
问题似乎与我预期的不同...
NSUserDefaults
似乎"waiting" 无法在允许访问其内容之前加载自身:
在我的代码中,我在它之前阅读了一个配置。
代码是:
let config :UserDefaults = UserDefaults();
// read config
必须更改为:
let config :UserDefaults = UserDefaults();
config.synchronize();
// read config
这是因为没有同步,watch 代码 运行 比配置的异步加载更快...这导致 nil
return 从配置中编辑我希望有...
这导致代码死亡,并终止了整个会话..
延迟一秒让异步进程完成加载,return期望值...
所以 - 在玩了很多次之后 - 我找到了一种让它工作的方法,但我有一个东西我没有想出如何绕过(让我发疯..)。
我有一个手表应用程序需要来自 GooglePlaces 的数据(iOS 尚无界面...)。所以 - 我使用 WCSession,并使用 phone,使用 sendMessage
,通过 phone 查询 GooglePlaces,将附近的地点返回到手表。
首先,GooglePlaces currentPlace
函数似乎是在调用它的同一线程上调用的(通过排队等待稍后使用)——这是一个问题,因为它被安排在程序关闭后的时间(因为函数 didReceiveMessage
在调用之前就已经退出了)。因此,我没有 运行 将它放在主队列上,而是启动一个线程并 运行 上面的代码....
它的一个问题是 replyHandler
必须在 session:didReceiveMessage
完成执行之前调用(否则如果应用程序处于后台模式,进程将被终止)。
所以我为绕过这个问题而构建的代码看起来像这样(注意我有一个嵌套的 cloudKit 代码......):
let queue = OperationQueue();
var finishedRunning = false;
queue.addOperation{
sleep(1);
self.placesClient?.currentPlace(callback: {
(placeLikelihoodList: GMSPlaceLikelihoodList?, error: Error?) -> () in
if let err = error {
retVal.removeAll();
retVal["error"] = err.localizedDescription;
finishedRunning = true;
return;
}
let predicate = NSPredicate(format: "selected = 1");
let query = CKQuery(recordType: "someInfo", predicate: predicate);
let privDb = CKContainer.default().privateCloudDatabase;
privDb.perform(query, inZoneWith: nil, completionHandler: {records, error in
if let err = error {
retVal.removeAll();
retVal["error"] = err.localizedDescription;
finishedRunning = true;
return;
}
retVal["completed"] = 1;
finishedRunning = true;
});
});
}
while !finishedRunning{
sleep(1);
}
marker = true;
replyHandler(retVal);
那些仔细阅读代码的人注意到我在上面添加了一个 sleep(1);
命令...在开始队列后立即。
我不清楚为什么,但是如果没有这个睡眠调用,就不会调用 GooglePlaces 回调!!
我真的很想删除这个特定的调用.. 有人知道为什么会这样吗? 如何绕过它?
(P.S。我不确定是否需要锁来保护 finishedRunning
.. 因为它有效,我认为 none 是必要的。
P.S。 #2 - 我知道它是 "dirty",但没有其他方法可以绕过它......因为我想要手表上的这些数据,我放弃了优雅......
谢谢!!
根据我的经验,sendMessage
的 replayHandler
不必在委托方法 returns 之前调用,但如果您确实希望保持该行为,您可以摆脱至少有一个 `sleep(1) 所以有:
<...>
queue.waitUntilAllOperationsAreFinished()
marker = true;
replyHandler(retVal);
我对 GooglePlaces 一无所知 API 所以我不知道为什么需要再睡一觉。综上所述,因为我不相信必须在委托方法 returns 之前调用 replayHandler
的基本假设,所以切换到执行此任务的更异步的方式可能会更好。
问题似乎与我预期的不同...
NSUserDefaults
似乎"waiting" 无法在允许访问其内容之前加载自身:
在我的代码中,我在它之前阅读了一个配置。
代码是:
let config :UserDefaults = UserDefaults();
// read config
必须更改为:
let config :UserDefaults = UserDefaults();
config.synchronize();
// read config
这是因为没有同步,watch 代码 运行 比配置的异步加载更快...这导致 nil
return 从配置中编辑我希望有...
这导致代码死亡,并终止了整个会话..
延迟一秒让异步进程完成加载,return期望值...