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

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

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

Мои данные хранятся в словаре и отправляются на часы с использованием метода WCSession 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. Сообщается, что усложнение перезагрузится, но ничего не происходит (возможная проблема с бюджетом?)

person bkSwifty    schedule 18.02.2019    source источник
comment
Я не уверен, что означает ваше обновление: это решение вашей проблемы? Или проблема остается прежней после того, как шаги выполняются в правильном порядке?   -  person Reinhard Männer    schedule 23.02.2019
comment
Это не решение. Я хотел показать, что обнаружил, что мое приложение выполняет функции в неправильном порядке, и я не знаю почему.   -  person bkSwifty    schedule 24.02.2019
comment
Вы это решили?   -  person Anton Bärwald    schedule 01.03.2019


Ответы (3)


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

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, который может вам больше помочь: source

person Anton Bärwald    schedule 27.02.2019

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

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

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

person Reinhard Männer    schedule 25.02.2019

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

person bkSwifty    schedule 01.03.2019