Какова последовательность обновления данных об осложнениях для Apple Watch?

Я следил за многими уроками в Интернете, чтобы узнать, как настроить усложнение. У меня нет проблем с установкой осложнения, как ожидалось.

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

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

struct data = {
var name: String
var startString: String
var startDate: NSDate
}

Следующий массив является контейнером для этих данных.

var dataArray = [data]

Это позволяет показать сложность, когда часы заблокированы.

func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
    handler(.ShowOnLockScreen)
}

Это позволяет переместиться во время путешествия на сложность.

func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
    handler([.Forward])
}

Здесь я установил время начала временной шкалы равным текущему.

func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate())
}

Здесь я установил время окончания временной шкалы равным 12 часам.

func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: (60 * 60 * 12)))
}

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

func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {

    let headerTextProvider = CLKSimpleTextProvider(text: "Some Data")
    let body1TextProvider = CLKSimpleTextProvider(text: "Some Data Time")
    let template = CLKComplicationTemplateModularLargeStandardBody()
    template.headerTextProvider = headerTextProvider
    template.body1TextProvider = body1TextProvider

    handler(template)
}

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

func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {

    createData()

    if complication.family == .ModularLarge {

        if dataArray.count != 0 {

            let firstData = dataArray[0]
            let headerTextProvider = CLKSimpleTextProvider(text: firstData.name)
            let body1TextProvider = CLKSimpleTextProvider(text: firstData.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            let headerTextProvider = CLKSimpleTextProvider(text: "No Data")
            let body1TextProvider = CLKSimpleTextProvider(text: "Create some data")
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider

            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        }

    } else {
        handler(nil)
    }

}

Здесь я создаю записи временной шкалы для всех данных, которые у меня есть в настоящее время.

func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {

    createData()

    var entries = [CLKComplicationTimelineEntry]()

    for dataObject in dataArray {

        if entries.count < limit && data.startDate.timeIntervalSinceDate(date) > 0 {

            let headerTextProvider = CLKSimpleTextProvider(text: dataObject.name)
            let body1TextProvider = CLKSimpleTextProvider(text: dataObject.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(timeInterval: (-10*60), sinceDate: data.startDate), complicationTemplate: template)
            entries.append(timelineEntry)

        }

    }

    handler(entries)

}

Это говорит часы, когда обновить данные усложнения.

func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: 60 * 60 * 6))
}

Здесь я сталкиваюсь с проблемами.

Как мне создать мои новые данные и перезагрузить график? Какой поток? Я не пытаюсь продлить срок, а скорее полностью заменить его. Я в полной растерянности. Документы Apple довольно расплывчаты, когда дело доходит до этого момента. Я знаю, что мне нужно реализовать следующие методы, но я не знаю как. Может ли кто-нибудь помочь мне заполнить этот код?

func requestedUpdateDidBegin() {
    createData() //I assume createData() goes here? If so, how do I populate the new timeline entries based on the results?
}

func requestedUpdateBudgetExhausted() {
    //This can't possibly be the case as I haven't gotten it to work once.
}

func reloadTimelineForComplication(complication: CLKComplication!) {
      //This method appears to do nothing.
}

Обновить:

Благодаря El Tea, у меня все получилось. Мне нужно добавить экземпляр CLKComplicationServer в requiredUpdateDidBegin и поместить метод reloadTimeline внутрь.

Вот обновленный код:

func requestedUpdateDidBegin() {
    print("Complication update is starting")

    createData()

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
        print("Timeline has been reloaded!")
    }

}

func requestedUpdateBudgetExhausted() {
    print("Budget exhausted")
}

2 ответа

Решение

Последовательность обновления сложности , выполняемая в течение интервала времени, соответствует следующей последовательности:

  • iOS вызывает вашу функцию requestedUpdateDidBegin() или же requestedUpdateBudgetExhausted() (Если ваш бюджет исчерпан, вы ничего не будете делать, пока не получите больше времени для выполнения.)
  • Внутри requestedUpdateDidBegin() ты должен позвонить reloadTimelineForComplication() или же extendTimelineForComplication() чтобы указать, какие из ваших сложностей вы хотите перезагрузить или добавить данные. Если вы этого не сделаете, ничего не произойдет!
  • В зависимости от того, если вы позвонили reload или же extendiOS звонит одному или обоим getCurrentTimelineEntryForComplication() а также getTimelineEntriesForComplication()
  • Независимо от того, обновили ли вы свое усложнение, iOS звонит getNextRequestedUpdateDateWithHandler() чтобы узнать, когда вы в следующий раз захотите повторить вышеуказанные шаги.

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

Процесс работает таким образом, что iOS не просит вас повторно создавать одни и те же данные. Это дает вам шанс в requestedUpdateDidBegin() решить, нуждается ли ваше осложнение в обновлении. Если это не так, ваш код должен просто вернуться. (Это сокращает время выполнения вашей сложности и помогает iOS не отключать ваше приложение от дальнейших обновлений за использование ежедневного бюджета). Но если у вас есть новые данные, вы должны сообщить iOS, позвонив reloadTimelineForComplication() или же extendTimelineForComplication()

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

func requestedUpdateDidBegin() {

    //Not shown: decide if you actually need to update your complication.
    //If you do, execute the following code:

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
    }
}

Обратите внимание, что помимо временных интервалов существуют и другие способы инициирования обновлений, включая push-уведомления, выполнение перезагрузок при запуске приложения наблюдения или использование среды Watch Connectivity с сеансом WCS, чтобы приложение вашего телефона отправляло данные обновления для немедленного отображения через transferCurrentComplicationUserInfo(), См. Обновление данных о сложности в документации Apple для получения дополнительной информации.

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

В ответе El Tea подробно рассказывается, как обновить услугу для watchOS 2.

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

  • Получить новые данные

  • обновить вашу модель, как только данные поступят,
  • обновите усложнение (путем перезагрузки или расширения временной шкалы), чтобы отобразить новые данные, доступные из модели, и, наконец,
  • обновите снимок док-станции вашего приложения, чтобы показать данные на док-станции

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

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

Я предоставил дополнительную информацию, а также ссылки на видео WWDC и пример кода в другом ответе.

Подводя итог изменения для watchOS 3

Используйте запланированные фоновые задачи вместо getNextRequestedUpdateDateWithHandler(),

Перезагрузите или продлите ваш график в задаче приложения, а не в requestedUpdateDidBegin(),

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