Какова последовательность обновления данных об осложнениях для 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
или же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 с сеансом WCS, чтобы приложение вашего телефона отправляло данные обновления для немедленного отображения через transferCurrentComplicationUserInfo()
, См. Обновление данных о сложности в документации Apple для получения дополнительной информации.
Я добился успеха в интервалах обновления тестирования симулятора всего за десять минут. Вы, вероятно, не должны обновлять это часто на реальных часах из-за бюджета времени выполнения, но это позволит вам протестировать свой код, не дожидаясь 12 часов.
В ответе El Tea подробно рассказывается, как обновить услугу для watchOS 2.
В watchOS 3 рекомендуемый способ держать ваши осложнения в актуальном состоянии включает использование фоновых задач обновления приложения. Вы можете использовать ряд фоновых задач для планирования и обработки расширения вашего приложения в фоновом режиме, чтобы:
Получить новые данные
- используя WKWatchConnectivityRefreshBackgroundTask для получения данных с телефона, или
- использование WKURLSessionRefreshBackgroundTask для загрузки данных с сервера
- обновить вашу модель, как только данные поступят,
- обновите усложнение (путем перезагрузки или расширения временной шкалы), чтобы отобразить новые данные, доступные из модели, и, наконец,
- обновите снимок док-станции вашего приложения, чтобы показать данные на док-станции
Это гораздо более функционально, а также энергосберегающе, поскольку не использует ежедневный бюджет выполнения ваших сложностей для извлечения данных или обновления модели.
Это также позволяет избежать любой сложности из-за неучтенных подходов, которые пытались асинхронно извлекать данные из источника данных усложнения, который когда-либо предназначался только для немедленного ответа на запросы.
Я предоставил дополнительную информацию, а также ссылки на видео WWDC и пример кода в другом ответе.
Подводя итог изменения для watchOS 3
Используйте запланированные фоновые задачи вместо getNextRequestedUpdateDateWithHandler()
,
Перезагрузите или продлите ваш график в задаче приложения, а не в requestedUpdateDidBegin()
,