Как запустить основное приложение iOS из приложения сопутствующего просмотра в фоновом режиме?

Ситуация:

Так как наши пользователи обновили iOS до 11 и/или WatchOS до 4, наше приложение iOS, похоже, не запускает никаких запланированных таймеров, когда приложение запускается нашим приложением WatchOS. Возможно, мы делаем что-то не так, когда начинаем наше основное приложение из приложения 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()
        }
    }
}

Затем в нашем основном приложении мы получаем сообщение и начинаем наш базовый контроллер:

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
}

Кажется, что все работает по-прежнему, мы правильно получаем GPS-адреса, все наши процессы начинаются, однако Timer объекты, которые запускаются, не срабатывают.

Это отлично работало до iOS 10, поэтому я подозреваю, что это имеет какое-то отношение к состояниям фона IOS 11, которые работают по-разному. Однако я не могу найти документацию об этом.

Дополнительная информация:

  • На iOS 10, когда мы начали наше основное приложение таким образом, приложение стало видимым в многозадачном представлении на iPhone. Теперь на iOS 11 он не отображается в многозадачном представлении, однако он работает на фоне. Я успешно вижу локальные уведомления, которые я планирую на заднем плане, я могу отлаживать активный код и при нажатии на значок приложения приложение сразу же доступно.
  • В нашем приложении WatchOS установлена ​​цель развертывания 2.0
  • Отладка через XCode с подключенным устройством, используя Debug → Attach to PID или Name → Введенное имя приложения. Затем запустите наше приложение из Apple Watch и отлаживайте.
  • Воспроизводимость на iOS 11.0.3 с помощью WatchOS 4.0 на iPhone 6

Вопросы: Каков наилучший способ начать наше основное приложение из приложения часов? Что-то изменилось в iOS 11/WatchOS 4 относительно состояния фона? Могу ли я найти документацию об этом? Может ли это быть ошибкой iOS?

Ответ 1

Все, что я могу вам предложить, - это подтверждение того, что это поведение действительно изменилось с 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")
}

Если вам требуется более последовательное, более продолжительное решение, вам может понадобиться использовать ваши обновления местоположения в качестве возможности выполнять любую работу, на которую работает данный таймер. Есть много других фоновых режимов, которые нужно преследовать.

Резюме ваших вопросов:

В: Каков наилучший способ начать наше основное приложение из приложения часов?
A: Ваш предлагаемый код - отличный способ запустить приложение-компаньон.

В: Что-то изменилось в iOS 11/WatchOS 4 относительно состояния фона?
A: Нет, особенно в отношении таймеров. Различное поведение, вероятно, является коррекцией.

В: Могу ли я найти документацию об этом?
A: Я не могу. Иногда вы можете сжать эту информацию от инженеров Apple на форумах или через вопросы поддержки уровня кода через свою учетную запись разработчика или перейти на WWDC.

Q: Может ли это быть ошибкой iOS?
A: Раннее поведение, вероятно, было ошибкой.

Ответ 2

Когда приложение закрыто и не работает в фоновом режиме, тогда местоположение никогда не отслеживается в iOS 11, это не ошибка iWatchOS 4 и iOS 11.

Изменения в отслеживании местоположения в iOS 11

следуйте этой документации: Изменения в отслеживании местоположений в iOS 11iOS 11 также вносит существенные изменения в существующие API. Одним из пострадавших районов является отслеживание местоположения.

Если ваше приложение использует только местоположение, когда приложение находится на переднем плане, как это делают большинство приложений, вам, возможно, вообще ничего не нужно будет менять; однако, если его одно из тех приложений, которое непрерывно отслеживает местоположение пользователей в течение дня, вы, вероятно, должны заказать некоторое время этим летом для внесения некоторых изменений в то, как вы выполняете отслеживание и тестирование возможных сценариев использования.

Например, рассмотрим эти два приложения снова; постоянное местоположение фона и значительное приложение для мониторинга изменения местоположения. Предположим, что пользователь отправляется на запуск с постоянным фоном. Theyll идут в бег, они возвращаются, они все время видят сплошную стрелу, и когда они смотрят на свою карту, они будут видеть каждый поворот и поворачивать их. Когда они устанавливают это приложение, которое использует значительный мониторинг изменения местоположения, они видят одно и то же, сплошную стрелку. Насколько известно пользователю, это приложение, вероятно, получает ту же информацию, что и приложение для отслеживания запуска. Поэтому, если пользователи неправильно интерпретируют наши сигналы, мы решили, что лучше всего исправить это, чтобы настроить способ указания использования местоположения.

watchOS имеет доступ ко многим из тех же технологий, что и в приложениях iOS; однако, даже если технология доступна, вы не сможете использовать ее так же, как на iPhone.

Не используйте фоновые режимы работы для технологии. В общем случае приложения "Наблюдение" считаются приложениями переднего плана; они запускаются только тогда, когда пользователь взаимодействует с одним из своих интерфейсов. В результате соответствующее расширение WatchKit не может использовать большинство режимов фонового исполнения для выполнения задач. может помочь эта документация: Использование технологий iOS для просмотра