获取 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",但没有其他方法可以绕过它......因为我想要手表上的这些数据,我放弃了优雅......

谢谢!!

根据我的经验,sendMessagereplayHandler 不必在委托方法 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期望值...