如何从后台的伴侣手表应用程序启动主iOS应用程序?

The*_*ter 12 iphone ios swift watchos wcsession

情况:

由于我们的用户已将iOS更新为11和/或将WatchOS更新为4,因此当我们的WatchOS应用程序启动应用程序时,我们的iOS应用程序似乎不会触发任何预定的计时器.也许我们在从WatchOS应用程序启动主应用程序时做错了什么.

上下文和代码:

我们的WatchOS应用程序是一个配套应用程序,可让用户通过按下按钮在后台启动/停止我们的iPhone应用程序.我们这样做是通过使用:

func startMainApp() {
    guard WCSession.default().isReachable == true else {
        print("Watch is not reachable")
        return
    }

    var data = [String : AnyObject]()
    data[WatchActions.actionKey()] = NSNumber.init(value: WatchActions.startApp.rawValue as Int)

    WCSession.default().sendMessage(data, replyHandler: { (result: [String : Any]) in
        let resultNumber = result[WatchActions.resultKey()] as? NSNumber
        let resultBool = resultNumber!.boolValue
        if resultBool == true {
            self.setModeActivated()
        } else {
            self.setModeActivationFailed()
        }

    }) { (error: Error) in
        if (error as NSError).code != 7012 {
            print("start app error: \(error.localizedDescription)")
            self.setModeActivationFailed()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我们的主应用程序中,我们收到消息并启动我们的基本控制器:

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
    if let actionNumber : NSNumber = message[WatchActions.actionKey()] as? NSNumber {
        if let watchAction : WatchActions = WatchActions(rawValue: actionNumber.intValue) {

            switch(watchAction) {
                case .isAppActive:
                    let result = BaseController.sharedInstance.sleepAndWakeUpController.isAwake()
                     replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])
                return

                case .startApp:
                    AudioController.sharedInstance().playActivatedSound()

                    let isRunningOnForeground = ApplicationStateHelper.isActive()
                    if isRunningOnForeground == false {
                        BaseController.sharedInstance.start(inBackground: true)
                    }
                    let result = true
                    replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])

                    DDLogInfo("[APPLE WATCH] [didReceiveMessage] [.startApp]")
                return
            }
        }
    }

    replyHandler([WatchActions.resultKey() : NSNumber.init(value: false as Bool)])
    return
}
Run Code Online (Sandbox Code Playgroud)

一切似乎都像以前一样工作,我们正确获取GPS位置,我们所有的流程都开始了,但是,Timer开始的对象,不要开火.

这在iOS 10之前完美运行,所以我怀疑这与iOS 11后台状态有关,它们的工作方式不同.但是,我似乎无法找到任何这方面的文件.

额外信息:

  • 在iOS 10上,当我们以这种方式启动主应用程序时,应用程序在iPhone的多任务视图中可见.现在在iOS 11上,它在多任务视图中不可见,但它确实在后台运行.我成功地看到了我在后台安排的本地通知,我可以通过活动代码进行调试,当点击应用程序图标时,应用程序立即可用.
  • 我们的WatchOS应用程序的部署目标为2.0
  • 通过XCode与设备连接进行调试,使用Debug - > Attach to PID或Name - > Entered app name.然后从Apple Watch启动我们的应用程序并进行调试.
  • 可在iOS 11.0.3上使用iPhone 6上的WatchOS 4.0重现

问题: 从手表应用程序启动主应用程序的最佳方法是什么?iOS 11/WatchOS 4中有关于背景状态的更改?我可以找到这方面的文件吗?这可能是iOS错误吗?

all*_*enh 6

我所能提供的只是确认此行为确实从 iOS 10 更改为 iOS 11。我怀疑 iOS 10(及更早版本?)上的行为不正确。即使开发人员开始依赖这种行为(我很确定我在上一个手表项目中使用了这种行为),Apple 也不会对改变无意的行为/他们认为不正确的行为有任何疑虑。

事实是,UIApplication当手表中的消息启动时 的状态是background. 除非使用特定的后台执行模式/后台任务,否则不应在应用程序处于后台时运行计时器。这个事实是众所周知的,通常在 iOS 开发人员职业生涯的早期就会遇到。我可以推测,当从手表启动时,计时器会在后台运行的事实是一个错误。

我不知道你的用例,即你为什么依赖这些计时器,但是你可以做的一件事很简单,就是创建一个空的后台任务,当应用程序启动时,它会给你更多的时间。

var backgroundTask: UIBackgroundTaskIdentifier?
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "app Start Task", expirationHandler: {
    guard let task = backgroundTask else { return }
    UIApplication.shared.endBackgroundTask(task)
})

let timer = Timer(timeInterval: 1, repeats: true) { (timer) in
    print("Running")
}
Run Code Online (Sandbox Code Playgroud)

如果您需要一个更一致、运行时间更长的解决方案,您可能需要利用您的位置更新作为一个机会来完成计时器当前的任何工作。还有很多其他的背景模式可以追求。

您的问题摘要:

问:从手表应用程序启动我们的主应用程序的最佳方式是什么?
答:您提议的代码是启动配套应用程序的好方法。

问:iOS 11/WatchOS 4 中关于后台状态有什么变化吗?
A:不,尤其是关于定时器。不同的行为很可能是一种更正。

问:我能找到这方面的文档吗?
答:我不能。有时,您可以在论坛上或通过开发者帐户的代码级支持问题或访问 WWDC 从苹果工程师那里获取这些信息。

问:这可能是 iOS 的错误吗?
答:较早的行为可能是错误。