Подтвердить что ты не робот

Каков поток обновления данных об осложнениях для 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)
}

Это позволяет продвигать Time Travel на усложнение.

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

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.
}

Update:

Благодаря El Tea у меня это работает. Мне нужно добавить экземпляр CLKComplicationServer для запросаUpdateDidBegin и поместить метод 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")
}
4b9b3361

Ответ 1

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

  • iOS вызывает вашу функцию requestedUpdateDidBegin() или requestedUpdateBudgetExhausted() (Если ваш бюджет исчерпан, вы ничего не получите, пока не получите больше времени выполнения.)
  • Внутри requestedUpdateDidBegin() вы должны вызвать reloadTimelineForComplication() или extendTimelineForComplication(), чтобы указать, какие из ваших осложнений вы хотите перезагрузить или добавить данные. Если вы этого не сделаете, ничего не произойдет!
  • В зависимости от того, вы вызвали reload или extend, iOS делает вызовы на один или оба из 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 с WCSession, чтобы ваше приложение для телефона отправляло данные об обновлении, которые будут отображаться сразу через transferCurrentComplicationUserInfo(). Подробнее см. Обновление данных об осложнениях в документах Apple.

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

Ответ 2

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

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

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

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

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

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

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

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

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

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