Осложнения Apple Watch не обновляются достоверно

У меня есть приложение для iPhone, которое отправляет данные из приложения iPhone прямо на циферблат, чтобы отобразить их как усложнение.

Я использую WatchConnectivity рамки для создания WCSession отправить данные на часы с телефона.

Мои данные хранятся в словаре и отправляются на часы с помощью WCSession"s transferCurrentComplicationUserInfo метод. (Этот метод можно использовать примерно 50 раз в день, и я знаю об этом - это не проблема.)

transferCurrentComplicationUserInfo Кажется, метод работает в первый раз, когда я пытаюсь отправить данные.

Моя проблема в том, что мое приложение для iPhone предназначено для вызова этой функции несколько раз за сеанс, и оно надежно работает только в первый раз.

Когда я отправляю второй набор данных, первый набор остается на сложность. Часто, когда я отправляю третий набор, появляется второй набор. Иногда второй набор появляется постоянно, а иногда он появляется только на короткую секунду перед отображением третьего набора.

Это противоречиво, и это проблема, с которой я столкнулся.

Есть что-то, что я настроил неправильно?

Код:

//iPhone code to send data to Apple Watch:

func sendComplication(complication: Complication) {
        guard let session = session else {
            delegate?.failedToSendComplication(reason: "Could not connect to your Apple Watch.")
            return
        }
        guard let context = convertComplicationToDictionary(complication: complication) else {
            delegate?.failedToSendComplication(reason: "Couldn't cast complication to a dictionary.")
            return
        }
        if session.remainingComplicationUserInfoTransfers > 0 {
            session.transferCurrentComplicationUserInfo(context)
            delegate?.didSendComplication()
        } else {
            delegate?.failedToSendComplication(reason: "Due to hardware limitations, you can only send a certain amount of complications in a day. You have exceeded that limit for today. You can still set complications from the Apple Watch app.")
        }
    }

// WatchKit Extension Delegate to receive and handle data sent from iPhone app

import WatchKit
import WatchConnectivity

class ExtensionDelegate: NSObject, WKExtensionDelegate {

    var session: WCSession?

    override init() {
        super.init()
        self.session = newWatchConnectivitySession()
    }

    func newWatchConnectivitySession() -> WCSession? {
        if WCSession.isSupported() {
            let session = WCSession.default
            session.delegate = self
            session.activate()
            return session
        }
        return nil
    }

    func reloadComplicationTimeline() {
        let server = CLKComplicationServer.sharedInstance()
        guard let activeComplicationFamilies = server.activeComplications else { return }
        for comp in activeComplicationFamilies {
            server.reloadTimeline(for: comp)
        }
    }

}

extension ExtensionDelegate: WCSessionDelegate {

    func sessionReachabilityDidChange(_ session: WCSession) {
        if session.activationState != .activated {
            self.session = newWatchConnectivitySession()
        }
    }

    // Receive info from iPhone app
    func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
        // Parse dictionary and update data source
        reloadComplicationTimeline()
    }

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        guard let error = error else { return }
        print(error.localizedDescription)
    }
}

// ОБНОВИТЬ //

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

Это последовательность событий:

  1. sendComplication вызывается из приложения iPhone
  2. ExtensionDelegate инициализируется в приложении Watch, настраивая WCSession
  3. Осложнение обновлено (слишком рано - это до WCSession получает новые данные)
  4. WCSession didReceiveUserInfo Метод делегата вызывается, данные анализируются, а источник данных обновляется (слишком поздно)
  5. Сложности сказано перезагрузить, но ничего не происходит (возможна проблема с бюджетом?)

3 ответа

Решение

Перезагрузка iPhone, Apple Watch и Mac устранила проблему.

Попробуйте следующее:

func reloadComplicationTimeline() {
    #if os(watchOS)
    let server = CLKComplicationServer.sharedInstance()
    if let activeComplicationFamilies = server.activeComplications {
    for comp in activeComplicationFamilies {
        server.reloadTimeline(for: comp)
    }
   #endif
}



func sendComplication(complication: Complication) {
        guard WCSession.default.activationState == .activated else {
            delegate?.failedToSendComplication(reason: "Could not connect to your Apple Watch.")
            return
        }
        guard let context = convertComplicationToDictionary(complication: complication) else {
            delegate?.failedToSendComplication(reason: "Couldn't cast complication to a dictionary.")
            return
        }
        #if os(iOS)
        if WCSession.default.isComplicationEnabled {
            let userInfoTranser = WCSession.default.transferCurrentComplicationUserInfo(context)
            delegate?.didSendComplication()
        } else {
            delegate?.failedToSendComplication(reason: "Due to hardware limitations, you can only send a certain amount of complications in a day. You have exceeded that limit for today. You can still set complications from the Apple Watch app.")
        }
        #endif
    }

Вот хороший пример от Apple, который может помочь вам больше: источник

Как вы описываете в своем обновлении, ваше приложение iPhone вызывает session.transferCurrentComplicationUserInfo(context) до того, как часы WCSession, Но документы говорят:

[TransferCurrentComplicationUserInfo(_:)] можно вызывать только в то время, когда сеанс активен, то есть для свойства Activation установлено значение WCSessionActivationState.activation. Вызов этого метода для неактивного или деактивированного сеанса является ошибкой программиста.

Поэтому я предлагаю вам реализовать (если вы еще этого не сделали) WCSessionDelegate функция session(_:activationDidCompleteWith:error:) (см. здесь), и передайте данные об осложнениях только после того, как сеанс был активирован.

Другие вопросы по тегам