как разбудить родительское приложение iOS с помощью sendMessage из complicationController

Я пытаюсь разбудить родительское приложение iOS, отправив сообщение из расширения watchkit.

Однако это работает только тогда, когда нижеприведенная функция sendMessage вызывается из watchApp/ViewController. Когда оно вызывается из ComplicationController, сообщение отправляется, но родительское приложение iOS теперь просыпается.

Любые советы приветствуются. (пожалуйста, укажите любую ссылку на код в Swift)

Здесь упрощенный код:

В AppDelegate и ExtensionDelegate:

override init() {
    super.init()
    setupWatchConnectivity()
}

private func setupWatchConnectivity() {
    if WCSession.isSupported() {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

В ExtensionDelegate: (здесь нет проблем, сообщение успешно отправлено)

func sendMessage(){
        let session = WCSession.defaultSession()
        let applicationData:[String:AnyObject] = ["text":"test", "badgeValue": 100 ]

        session.sendMessage(applicationData, replyHandler: {replyMessage in
            print("reply received from iphone")
            }, errorHandler: {(error ) -> Void in
                // catch any errors here
                print("no reply message from phone")
        })
    }
    print("watch sent message")

}

В AppDelegate: (не получено, если приложение iOS не запущено/не на переднем плане)

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    let text = message["text"] as! String
    let badgeValue = message["badgeValue"] as! Int

    dispatch_async(dispatch_get_main_queue()) { () -> Void in

        print("iphone received message from watch App")
        self.sendNotification(text, badgeValue: badgeValue)
        let applicationDict = ["wake": "nowAwake"]
        replyHandler(applicationDict as [String : String])

    }

}

вот как функция вызывается из контроллера усложнения (который отправляет сообщение, но не пробуждает родительское приложение):

  func requestedUpdateDidBegin(){

        dispatch_async(dispatch_get_main_queue()) { () -> Void in

            let extensionDelegate = ExtensionDelegate()
            extensionDelegate.loadData()

        }
    }

person TPeter    schedule 04.11.2015    source источник
comment
Я только что протестировал ваш код на симуляторах и на iPhone/Watch. Это будит приложение, даже если я его никогда не открывал. Это работает, когда приложение работает, когда приложение находится в фоновом режиме и когда приложение полностью убито.   -  person joern    schedule 05.11.2015
comment
С чего вы взяли, что приложение не проснулось?   -  person joern    schedule 05.11.2015
comment
спасибо Йорн за ваши усилия. Действительно ценится. Только что проверил то же самое только с вышеприведенным кодом, и вы правы. Действительно странно. Кажется, проблема не в приведенном выше коде, а в том, как я его называю. В моем приложении я вызываю sendMessage (который находится в ExtensionDelegate) из ComplicationController, и в этом случае сообщение отправляется, но родительское приложение не просыпается. Если вместо этого я запускаю sendMessage из приложения/из ViewController, сообщение отправляется, и родительское приложение действительно просыпается. (откуда я знаю, по ответу получено или нет по часам)   -  person TPeter    schedule 05.11.2015
comment
Итак, я предполагаю, что это связано с конкретным кодом сложности. К сожалению, у меня нет большого опыта с осложнениями, поэтому я не могу помочь в этом.   -  person joern    schedule 05.11.2015
comment
Я обновил вопрос выше, указав на вызов этой функции из ComplicationController.   -  person TPeter    schedule 06.11.2015
comment
У меня тоже есть эта проблема. В вашем методе requiredUpdateDidBegin() я предполагаю, что код должен быть extensionDelegate.sendMessage(). А у тебя когда-нибудь это работало?   -  person mginn    schedule 01.05.2016


Ответы (1)


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

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

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

Задача вашего класса источника данных — как можно быстрее предоставить ClockKit любые запрошенные данные. Реализации ваших методов источника данных должны быть минимальными. Не используйте методы источника данных для извлечения данных из сети, вычисления значений или выполнения каких-либо действий, которые могут задержать доставку этих данных. Если вам нужно получить или вычислить данные для вашего усложнения, сделайте это в своем приложении iOS или в других частях вашего расширения WatchKit и кэшируйте данные в месте, где ваш источник данных усложнения может получить к ним доступ. Единственное, что должны делать ваши методы источника данных, — это брать кэшированные данные и помещать их в формат, требуемый ClockKit.

Как обновить усложнение?

Преимущество обоих этих подходов заключается в том, что для выполнения требуется только одно обновление.

person Community    schedule 01.05.2016
comment
Разве что-то вроде transferUserInfo не завершается только при открытии приложения Watch? - person mginn; 01.05.2016
comment
transferUserInfo переносит информацию в фоновом режиме, даже если приложение или расширение приостановлено или завершено, поэтому сама передача будет завершена . Данные будут ожидать, и didReceiveUserInfo будет вызываться при открытии приложения. Как правило, это обеспечивает лучший пользовательский опыт, поскольку пользователю не нужно ждать, пока часы запросят и получат данные. Благодаря кэшированию самых последних данных они будут доступны для следующего запланированного обновления временной шкалы. - person ; 01.05.2016
comment
Единственная проблема заключается в том, что пользователь никогда не открывает приложение, поэтому вместо этого я использую transferCurrentComplicationUserInfo. - person mginn; 01.05.2016
comment
Это предпочтительный способ обновления расширения, но ваше расширение для часов по-прежнему может получать другие переданные данные, даже если само приложение не открыто. - person ; 01.05.2016