Осложнения 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)
}
}
// ОБНОВИТЬ //
После дальнейшей проверки я теперь вижу, что шаги происходят не по порядку.
Это последовательность событий:
sendComplication
вызывается из приложения iPhoneExtensionDelegate
инициализируется в приложении Watch, настраиваяWCSession
- Осложнение обновлено (слишком рано - это до
WCSession
получает новые данные) WCSession didReceiveUserInfo
Метод делегата вызывается, данные анализируются, а источник данных обновляется (слишком поздно)- Сложности сказано перезагрузить, но ничего не происходит (возможна проблема с бюджетом?)
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, который может помочь вам больше: источник
Как вы описываете в своем обновлении, ваше приложение iPhone вызывает session.transferCurrentComplicationUserInfo(context)
до того, как часы WCSession
, Но документы говорят:
[TransferCurrentComplicationUserInfo(_:)] можно вызывать только в то время, когда сеанс активен, то есть для свойства Activation установлено значение WCSessionActivationState.activation. Вызов этого метода для неактивного или деактивированного сеанса является ошибкой программиста.
Поэтому я предлагаю вам реализовать (если вы еще этого не сделали) WCSessionDelegate
функция session(_:activationDidCompleteWith:error:)
(см. здесь), и передайте данные об осложнениях только после того, как сеанс был активирован.