📱Как работают таймлайны и как обновлять виджеты правильно
В этой статье подробно рассмотрены возможности обновления контента в Home Screen и Lock Screen виджетах для iOS 16.
В iOS 14 Apple представила Home Screen Widgets. Можно было бы сказать, что так впервые появились виджеты, но это не правда – они и до этого существовали в iOS как Today Extensions, но совершенно не пользовались популярностью. То ли дело взорвавшие тренды Home Screen Widgets. Практически день в день с выходом в релиз новой 14-ой iOS приложения для кастомизации Home Screen завоевали все топы и не опускаются до сих пор, а это уже 2 года. Что же можно о них рассказать интересного и какие есть возможности в работе с ними? Как по мне, не так сложно их сделать, как разобраться в обновлении контента на них. Я предлагаю рассмотреть, что такое таймлайны у виджетов (актуально как для home screen, так и для lock screen) и как их менять в зависимости от вполне реальных задач.
Для обновления контента на виджете создается таймлайн-провайдер – это буквально временная шкала обновлений виджета. Таймлайн-провайдер содержит в себе массив entry-объектов, которые хранят в себе дату и время смены контента и сам контент, который необходимо отобразить. Выходит, что таймлайн-провайдер – это некоторое правило: как часто и с какой информацией будет меняться виджет. Например, мы каждый час будем менять background-картинку на виджете. Пусть у нас будет для этого 10 разных картинок. Вот так будет выглядеть код для этой задачи.
Так как мы указали политику обновления policy: .atEnd
, WidgetKit запросит новый таймлайн-провайдер после последней даты в entry-объектах. Таким образом, по истечении нашего созданного 10-ти часового timeline provider’а будет создан такой же новый 10 часовой таймлайн-провайдер и наш виджет будет обновлять 10 картинок бесконечно. Кроме .atEnd
есть еще следующие:
.never
– новый таймлайн-провайдер не создастся по истечении текущего, то есть контент на виджете больше не будет меняться..after(Date())
– новый таймлайн создастся после этой даты.
На каждый виджет система выделяет некоторую память, объем которой зависит от множества факторов, один из которых – как часто пользователь пользуется виджетом, то есть смотрит на него. Ресурсы, выделенные системой на один виджет, применяются к 24-часовому периоду, но не к календарным суткам. WidgetKit настраивает 24-часовое окно в соответствии с ежедневной моделью пользования телефоном юзером, что означает, что выделенные ресурсы на день не обязательно сбрасывается ровно в полночь. Для виджета, который пользователь часто просматривает, дневной бюджет ресурсов обычно включает от 40 до 70 обновлений таймлайн-провайдера. Это примерно соответствует перезагрузке виджета каждые 15-60 минут, но на количество обновлений таймлайн-провайдера могут повлиять и другие факторы, значительно их уменьшив. Это означает, что обновлять таймлайн-провайдеры часто мы не можем, а именно обновления чаще 5 минут не поддерживаются. В задачах, где мы точно знаем, на какой контент мы будем обновлять виджет, это ограничение нам ничего и не сделает. Мы все так же сможем обновлять часы каждую минуту, например, вот как будет выглядеть создание таймлайна:
Тут таймлайн мы обновляем каждый час, и внутри таймлайна добавляем 60 entry-объектов на каждую минуту, так мы сможем обновить текст с нужным значением времени. Мы можем добавить и больше 60 entry-объекта – 120, 240 и далее, но и слишком много не получится. Например, при попытке создать entry-объекты сразу на год 60*24*365, бюджет выделенной памяти заполнится и виджет вообще не будет менять информацию. А можем ли мы менять некоторую информацию чаще, чем 1 раз в минуту? Да, можем. Есть два способа это сделать. Если мы хотим виджет с часами с отображением секунд, то во вью самого виджета нам нужно использовать следующее:
И тогда мы увидим на виджете время такого формата 14:30:25, которое будет меняться каждую секунду и нам не нужно ничего особенного прописывать при создании таймлайна.
Еще мы просто можем задать таймлайн с обновлением каждую секунду, вот так:
Но и тут, конечно же, мы упремся в переполнение выделенной на виджет памяти и в какой-то момент виджет просто перестанет работать, пока память не обновится. Да, это не полностью рабочий вариант, но и он может использоваться, если, например, мы хотим сделать анимационные виджеты, например, гифки. Предсказать точное время работы такого виджета будет крайне сложно, но первые 15-20 секунд точно обеспечены.
Как нам обновлять погодный виджет? Или батарейный? Или любой другой, где мы не можем знать данные наперед и создать сразу таймлайн-провайдер на день/месяц. Мы создаем таймлайн-провайдер с одним entry-объектом и указываем правило обновления – после определенной даты. Пусть это будут 20 минут.
Обновлять таймлайн-провайдер чаще 5 минут мы не можем, соответственно, и обновлять некоторую быстроменяющуюся информацию тоже.
Я постаралась подробно рассказать про работу таймлайн-провайдера и способы обновления виджетов. Надеюсь, что эта статья была полезной. Я буду рада фидбэку и комментариям. Спасибо!
Савицкая Надежда, iOS-разработчик.