Как сделать свои виджеты на ios 14
Будь в курсе последних новостей из мира гаджетов и технологий
iGuides для смартфонов Apple
Меняем изображение в виджете «Фото» на iPhone с iOS 14

21 декабря 2020, 19:16
Операционная система iOS 14 привнесла на домашний экран совершенно новую систему виджетов. Теперь вы можете настроить внешний вид своего рабочего стола с помощью сотен различных вариантов. Виджет «Фото» — один из самых популярных. Он является частью фирменной галереи Apple.
Этот виджет доступен в трех размерах. Отображаемое фото меняется каждый час. Однако, вы не можете повлиять на то, какой снимок будет отображаться в любой момент времени. Вместо этого приложение «Фото» динамически выбирает кадр для отображения в виджете.

Виджет «Фото» позволяет пользователям просматривать на зацикленные изображения из их библиотеки, но если вы хотите отобразить конкретную фотографию или подборку снимков, то вам потребуется стороннее приложение. В App Store есть много различных программ-виджетов, которые позволяют выполнять эти действия. Не забудьте подписаться на канал нашего техноблога в Telegram https://t.me/appdatemedia .
Одно из самых простых приложений называется Photo Widget: Simple . Оно позволяет выбирать до 30 фотографий для отображения на виджете для главного экрана. Приложение поддерживает все три размера, вы также сможете установить временной интервал для смены отображаемого снимка.
Следующие шаги объясняют, как настроить одной фотографии в виджете Photo Widget: Simple. Не забудьте, что у него также имеются аналоги в магазине приложений.
- Загрузите приложение Photo Widget: Simple .
- Откройте его,
- Коснитесь значка + в центре экрана.
- Выберите фотографию, которую хотите отобразить на главном экране.
- Вернитесь на главный экран.
- Удерживайте любое пустое пространство рабочего стола.
- Коснитесь + в верхнем левом углу.
- Перейдите к разделу Photo Widget: Simple.
- Просматрите три доступных размера виджета, проводя пальцем влево и вправо. Выберите один из доступных размеров в соответствии с вашими предпочтениями, нажав «Добавить виджет».
- Теперь вы можете перетащить виджет и разместить его в любом месте рабочего стола.
- Коснитесь кнопки «Готово».
Чтобы добавить более одной фотографии для отображения в виджете, просто повторите предыдущие шаги, выбрав нужные снимки. По завершению настроек вы можете скрыть иконку приложения с рабочего стала. После этого найти его можно будет в «Библиотеке приложений».
Как настроить значки и виджеты iOS 14
С приходом iOS 14 У нас было много новостей, некоторые лучше, чем другие, например, постоянное уменьшение заряда батареи, которое влияет на многих пользователей, особенно на тех, у кого есть старые устройства, такие как iPhone X. Однако не все плохие новости в последние дни с прибытие iOS 14.
Появились новые функции, теперь можно настраивать значки и создавать свои собственные виджеты в iOS 14 самым простым способом, который вы могли представить, узнайте вместе с нами, как это можно сделать. Как всегда, в Actualidad iPhone мы научим вас, как максимально эффективно использовать iPhone или iPad.
- 1 Настроить значки
- 2 Настройте свои виджеты в полной мере
Настроить значки
Способ настройки иконок — самый простой из возможных. Я всегда рекомендую вам смотреть видео, которые сопровождают эти totorales, чтобы вам было легче выполнить все шаги, наблюдая их вживую, однако мы всегда можем оставить вас здесь, чтобы написать лучшие подробности. То, что мы собираемся сделать, — это относительно простая логика применения, и для этого нам понадобится одно из приложений, которые компания из Купертино отдала больше всего, мы говорим о ярлыках.
Мы собираемся выполнить следующие простые шаги, но во-первых, мы выбираем или сохраняем в нашей галерее ту фотографию или значок, которые мы захотим использовать позже в качестве пользовательского значка. Для этого мы можем сделать их сами через PhotoShop или инструмент, который мы считаем подходящим, или, как показано в нашем видео-руководстве, загружая их напрямую через Google Images, я оставляю это на ваше усмотрение, но держите его под рукой в фотогалерее. вашего iPhone на потом. Теперь мы просто перейдем в приложение Shortcuts и сделаем следующие шаги:

- Нажмите кнопку «+», чтобы добавить новый ярлык.
- Выбираем вариант «Скрипт»
- Выбираем вариант «Открыть приложение . »
- Теперь в «Select» нажимаем и выбираем приложение, которое хотим открыть
- После выбора нажимаем кнопку «…» в правой верхней части.
- Выбираем «Показать на главном экране» и нажимаем на иконку изображения
- Теперь выбираем фотографию и назначаем ее
Готово, мы уже создали собственный ярлык для имитации значка приложения. Лично мне эта функция не очень нравится, потому что она создает небольшую «задержку» между щелчком по значку и тем, сколько времени требуется, чтобы открыть приложение, но Кажется, что это стало настоящей тенденцией с # iOS14HomeScreen, поэтому мы все равно покажем вам это.
Настройте свои виджеты в полной мере
Вторая новинка — это как раз возможность создавать и редактировать собственные виджеты, и для этого мы будем использовать приложение, которое было запущено в iOS App Store и которое вы должны скачать как можно скорее. Мы говорим о Widgetsmith, приложении, которое теоретически является полностью бесплатным, хотя в нем есть некоторые встроенные платежи. Остальное уже история. После установки приложения мы сможем увидеть, что у нас есть три варианта виджетов традиционного стандарта, который Apple реализовала для своей собственной системы.
Виджетсмит бесплатно Скачать приложение
После установки приложения мы можем ввести и выбрать конкретный размер виджета. При входе мы можем настроить от источника до низа и содержимое, которое отображает виджет. Понятно, что на данный момент он ограничен определенной информацией о погоде, и еще одна деталь заключается в том, что он показывает только контент на английском языке, но, несомненно, он скоро будет обновлен, чтобы отображать больше другого контента и на большем количестве языков. На данный момент некоторые из его функций являются платными, а другие полностью бесплатными, нам придется над этим поработать.
А пока присоединяйтесь к вызову, зайдите в Twitter и с хэштегом # iOS14HomeScreen процитируйте @A_iPhone (наша учетная запись Twitter) и покажите нам, какие у вас креативы, с помощью этих новых инструментов настройки. Вы также можете присоединиться к нашему каналу Telegram (LINK) и покажите, как это получилось.
Содержание статьи соответствует нашим принципам редакционная этика. Чтобы сообщить об ошибке, нажмите здесь.
Полный путь к статье: Новости iPhone » iOS » Система IOS 14 » Как настроить значки и виджеты iOS 14
Будьте первым, чтобы комментировать
Делаем свой Widget в iOS 14
В iOS 14 и macOS 11 Apple представили Widgets. Еще один способ взаимодействия пользователя с приложением. В данной статье рассмотрим основные принципы работы WidgetKit и интегрируем свой Widget в готовый проект.
Введение
Что такое Widget?
Widget показывает главную информацию вашего приложения, без открытия самого приложения. Так же виджеты помогают сделать ваш домашний экран более персонализированным.
Widgets галерея
Пользователи могут найти виджеты в галерее виджетов, там же они могут выбрать размер для виджета. Всего есть 3 размера для виджетов: small, medium и large.
Для того чтобы добавить виджет на экран нужно войти в режим редактирования домашнего экрана и нажать на плюсик в верхнем левом углу, откроется галерея, где будут представлены виджеты приложений, но только от тех приложений, которые их поддерживают. При нажатии на конкретный виджет можно будет выбрать его тип и его размер, например приложение Stocks имеет 2 типа виджетов Watchlist и Symbol, причем для Watchlist представлены все 3 размера, а для Symbol только один.
Основные принципы
Главное предназначение виджета это показать небольшой объем информации пользователю, актуальной в данный момент времени. Определение этого одного предназначение является первым шагом для построения хорошего пользовательского опыта. Поэтому основные принципы включают в себя
- Придерживайтесь одной идеи. Главная идея вашего приложения должна быть отображена в вашем виджете. Например приложение Weather может показывать погоду для одной локации, приложение Stocks последние котировки акций.
- Для каждого размера показывайте только ту информацию, которая прямо относится к вашей идее. Для Stocks это может быть отображение только 3-х акций для маленького размера с указанием только названия и цены, а для большого размера это будет отображение более 5 акций с более детальной информации по ним.
- Не создавайте виджет, который ничего не делает, а только открывает приложение. Пользователь ожидает возможность просмотра важной информации без открытия приложения.
- Сделайте поддержку нескольких размеров, это улучшит пользовательский опыт. Реализация одного маленького размера приведет к тому, что на бОльших размерах много свободного пространства будет не задействовано, что не придает привлекательности приложению.
- Информация показанная на виджете должна меняться в течении дня. Если информация будет статичной или будет меняться очень редко, то будет ли польза от такого виджета? Поэтому важно чтобы информация менялась в течении дня, для приложения Calendar это будут предстоящие митинги, для Weather текущая погода.
Конфигурация виджета

- Позвольте пользователю конфигурировать виджет, когда это имеет смысл. Например для Weather можно выбрать город, откуда будет показываться погода, для Stocks доступен выбор акции, котировки который вы хотите мониторить.
- Когда нажимаете на виджет, убедитесь что открывается нужный экран приложения. Если нажали на пару USD/RUB в Stocks от должен открыться экран с детальной информацией по этой паре, а не какая-то другая.
- Избегайте большого количества нажимаемых элементов на виджете. Можно иметь несколько элементов на которые можно нажать, но тут надо быть аккуратным, чтобы у пользователя не возникло проблем с попаданием пальцем на нужный элемент виджета.

- Дайте пользователю понять, что будучи залогиненным он получит больше информации. Для приложения по бронированию билетов или отелей, аутентификация пользователя в системе предоставляет ему больше информации, например номер брони, QR-код и многое другое.
Обновление виджета
- Поддерживайте обновленное состояние вашего виджета. Для того чтобы информация на виджете оставалась актуальной, его нужно периодически обновлять. Виджеты не поддерживают обновление в режиме реального времени, так же система может ограничить вас в частоте обновления виджета. Поэтому нужно подойти к этому вопросы с осторожностью, например приложение Почта России может обновлять статус посылки раз в час или в два, этого будет достаточно, а вот приложению для трейдинга обновление раз в час может быть недостаточно и нужно будет обновляться чаще.
- Позвольте системе обновлять даты и время в вашем виджете. Частота обновления виджета ограничена и поэтому переложите обязанность обновления даты и времени системе.
- Показывайте контент быстро. Когда вы определяете частоту обновления контента, помните, что вам не обязательно прятать устаревшие данные за каким-то плейсхолдером, лучшее показать что-то старое, чем какой-то пустой скелетон.
Дизайн виджета
Пройдемся кратко по дизайну.
- Если необходимо, то отобразите название или логотип вашего приложения через цвет, текст или картинку . Сделайте так, что контент виджета и брэндинг не мешались друг другу, зачастую это и не нужно, потому что название вашего приложения отображается под виджетом.
- Поддерживайте баланс плотности информации. Если на виджете будет мало информации, то тогда возникнет вопрос в необходимости иметь этот виджет, если будет слишком много информации, то пользователю будет сложно в ней ориентироваться и ее воспринимать.
- Используйте цвета разумно. Насыщенные, яркие цвета привлекают внимание пользователей, но тут нужно не перестараться, а просто придерживаться цветовой палитры приложения.
- Поддержка темной темы. Виджет должен выглядеть соответствующе на темной и светлой темах.

- Рассмотрите использование шрифта SF Pro. Согласитесь, что приятно, когда все виджеты на домашнем экране имеют одинаковый шрифт, а не когда у каждого свой.
- Используйте текстовые элементы в виджете. Убедитесь, что текст масштабируется нормально, не растрируйте его, иначе это приведет к проблем с VoiceOver.
- Проектируйте реалистичную превьюшку для отображения в галерее виджетов. Покажите какими возможностями обладает этот виджет, вы так же можете отобразить реальные данные здесь, но если загрузка этих данных занимает много времени, то может просто заменить моками.
- Используйте скелетоны, чтобы дать понять пользователю структуру виджета. Виджет показывает скелетон, когда данные все еще загружаются.

- Напишите короткое, но емкое описание для виджета. В Галереи виджетов есть описание для каждого виджета, что именно он делает. Рекомендуется начинать это писание с глагола, например «Следить за предстоящими митингами», «Посмотреть погоду в указанной местности» и т.д.
Поддержка различных размеров экранов
Виджеты масштабируются к размеру экрана на различных устройствах, начиная с iPhone 6s заканчивая iPhone 11 Pro Max.
- Убедитесь что картинки, соответствуют размерам виджета. Ниже представлена таблица с размерами виджетов.

- Уравняйте скругление углов элементов в вашем виджете со скруглением углов самого виджета. Позаботесь о том, чтобы контент виджета выглядел хорошо со скругленными углами этого виджета, в этом может помочь ContainerRelativeShape.
- Рекомендуется использовать стандартные отступы между элементами. Стандартный отступ это 16 поинтов, использование стандартного отступа поможет разместить элементы в читабельном виде и сделает контент более разборчивым для пользователя.
Smart Stack
Вы можете организовывать виджеты в стеки, сам по себе стек это просто список виджетов, где в данный момент показывается только один виджет.
Когда у пользователя есть стек, то он может включить Smart Rotate (включено по умолчанию), который будет перемешивать и показывать только тот виджет, который он посчитает релевантным в данный момент времени.
Встречаем WidgetKit
Определение
WidgetKit позволяет пользователю получить доступ к возможностям вашего приложения с помощью вынесения виджета на iOS Home screen или в macOS Notification Center.
С тремя различными размерами для виджета (small, medium, large) у пользователя есть выбор, сколько именно информации он хочет видеть.
Создание Widget’a
Чтобы создать свой виджет, вам нужно добавить Widget Extension к своему приложению. Сам контент виджета создается с помощью SwiftUI, чтобы настроить виджет используется Timeline Provider, он используется для того, чтобы сказать виджету когда ему обновлять свой контент.

Чтобы позволить пользователю конфигурировать виджет вы добавляете свой SiriKit intent definition, остальное сделает WidgetKit за вас и предоставит пользователю кастомизированный интерфейс.
Создаем Widget extension
Итак представим у нас есть iOS приложение и теперь мы хотим добить поддержку виджетов, рассмотрим шаг за шагом, как это можно сделать.
Определение главной идеи для виджета
Перво-наперво нужно определиться с главной идеи для виджета, какую проблему он будет решать, будет ли он полезен пользователю, также желательно соотнести вашу идею с эпловскими гайдлайнами.
Приложение
Существующий проект
Представим, что у нас уже есть готовое приложение и теперь мы хотим к нему прикрутить виджеты.
В данной статье будет рассматривается простое приложение Рейтинг Игроков, которое состоит из 2х экранов — таблицы с рейтингом профилей и детальной информации по каждому профилю. Исходный код можно найти в конце статьи.
Добавление виджета в проект
Для того чтобы добавить виджет в приложение нужно выбрать File -> New -> Target, на вкладке iOS выбираем Widget Extension, даем имя нашему виджету, например LadderWidget . В проект добавится новый таргет, также файл LadderWidget.swift, где будет сразу добавлены все необходимые классы. Уже начиная с этого моменты, можно запустить виджет, выбрав соответствующий таргет, и увидеть результат на экране симулятора.

Основные классы
Рассмотрим какие классы создал для нас Xcode.
- LadderWidget
- LadderWidgetEntryView
- Provider
- SimpleEntry
Как мы увидим, на самом деле это не классы, а структуры, кратко пройдемся по каждой из этих структур.
- SimpleEntry — слепок, который содержит данные для отображения их на виджете;
- Provider — предоставляет таймлайн из слепков для виджета;
- LadderWidgetEntryView — View для виджета, тут определяется как будет выглядеть виджет;
- LadderWidget — наследник Widget , это непосредственно и есть наш виджет.
Как данные обновляются на виджете? iOS использует механизм слепков, то есть виджету предоставляются таймлайн слепков из провайдера и он их показывает на определенном интервале времени в будущем.
Проведем небольшой рефакторинг и переименуем наши структуры.
LadderEntry
Данные для виджета определяются именно в этой структуре путем добавления соответствующих свойств.
struct LadderEntry: TimelineEntry < let date: Date // your properties ->let name: String >
То есть если ваш виджет будет показывать, например, погоду, то у вас скорее всего будут свойства let cityName: String , let cityTemperature: Double , ну и let date: Date , последнее свойство определяет дату когда WidgetKit обновит виджет и является обязательным, чтобы следовать протоколу TimelineEntry .
LadderProvider
Кто-то должен предоставлять LadderEntry для виджета и за это ответственен LadderProvider . Эта структура следует протоколу TimelineProvider , взлянем на определение.
protocol TimelineProvider < associatedtype Entry : TimelineEntry typealias Context = TimelineProviderContext func placeholder(in context: Context) ->Entry func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) >
- placeholder(in context: ) — возвращает слепок, который будет использоваться как отображения шаблонной версии виджета.
- getSnapshot(in context: , completion:) — возвращает слепок, который представляет текущее время и состояние виджета.
- getTimeline(in context: , completion:) — возвращает массив слепков в виде таймлайна для текущего времени и будущих случаев обновления виджета.
LadderWidgetEntryView
Это обычное View , которое определяет, как будет выглядеть наш виджет.
struct LadderWidgetEntryView : View < var entry: LadderProvider.Entry var body: some View < Text(entry.date, style: .time) >>
LadderWidget
LadderWidget — наследник Widget , если посмотреть на определение протокола Widget , то можно заметить, что оно сильно напоминает обычный View , так же через body определяется контент виджета, но тут также указывается, как виджет будет конфигурироваться статически или динамически, а также здесь указывается провайдер для виджета.
@main struct LadderWidget: Widget < let kind: String = "LadderWidget" var body: some WidgetConfiguration < StaticConfiguration(kind: kind, provider: LadderProvider()) < entry in LadderWidgetEntryView(entry: entry) >.configurationDisplayName("My Widget") .description("This is an example widget.") .supportedFamilies([.systemMedium, .systemSmall]) > >
- .configurationDisplayName(_) указывает название виджета в галерее виджетов;
- .description(_) указывает описание в галерее виджетов;
- .supportedFamilies(_) указывает какие размеры будет поддерживать виджет, если не указать, то будут поддерживаться все размеры.
@main перед определением виджета обозначает «точку входа» для данного таргета, а именно то, что при запуске будет показан именно Ladder Widget.
Ladder Widget начало
Размеры виджета — .widgetFamily
Наше приложение показывает список профилей, было бы неплохо иметь виджет, который показывает данные конкретного профиля, причем для виджета с маленьким размером это будет просто текст, а для среднего размера картинка и текст.

Начнем с LadderEntry , для этого добавим соответствующую поле.
struct LadderEntry: TimelineEntry
Так же надо не забыть включать файлы, классы которых используется в таргете виджета, в таргет виджета. Для Profile.swift это будет выглядеть так.

Теперь обновим как будет отображается виджет.
struct LadderWidgetEntryView : View < var entry: LadderProvider.Entry @Environment(\.widgetFamily) var family @ViewBuilder var body: some View < switch family < case .systemSmall: ProfileInfoView(profile: entry.profile) default: ProfileView(profile: entry.profile) >> >
С помощью @Environment(\.widgetFamily) можно получить доступ к размеру виджета и в зависимости от значения показывать просто текст для маленького размера или картинку и текст для среднего размера.

Чтобы можно было сразу увидеть, как виджеты будут выглядеть для разных размеров, можно заключить их в Group .
struct LadderWidgetEntryView_Previews: PreviewProvider < static var previews: some View < Group < LadderWidgetEntryView(entry: LadderEntry(date: Date(), profile: sampleProfile)) .previewContext(WidgetPreviewContext(family: .systemSmall)) LadderWidgetEntryView(entry: LadderEntry(date: Date(), profile: sampleProfile)) .previewContext(WidgetPreviewContext(family: .systemMedium)) >> >
Неплохо было бы иметь возможность как-то выбирать какой профайл показывать на виджете, это можно сделать и для этого нам понадобится убрать статическую конфигурацию и добавить динамическую.
Конфигурация виджета — IntentConfiguration
Чтобы добавить динамическую конфигурацию, нужно в LadderWidget заменить StaticConfiguration на IntentConfiguration , для этого нажимаем File -> New -> File -> SiriKit Intent Definition File. Называем файл LadderIntents.intentdefinition.
Конфигурация определяется Intent , Intent определяет некоторые свойства для виджета, их много, рассмотрим только некоторые. Но перед этим создадим модель для Intent , это будет списком профилей из которых будет выбирать пользователь.
Нажимаем на плюсик и добавляем Enum , заполняем поля этого перечисления.

Гуд, теперь создадим сам Intent , нажимаем на плюсик и кликаем New Intent, называем его ProfileSelection и конфигурируем, как показано на картинке.

Xcode под капотом сгенерирует для нас класс ProfileSelectionIntent . Теперь заменим конфигурацию в нашем LadderWidget .
IntentConfiguration(kind: kind, intent: ProfileSelectionIntent.self, provider: LadderProvider())
Компилятор будет ругаться, что LadderProvider не следует протоколу IntentTimelineProvider , исправляем это, для этого просто следуем протоколу IntentTimelineProvider вместо TimelineProvider и обновляем сигнатуры функций соответственно.
Раз мы добавили ProfileSelectionIntent , значит пора его где-то использовать, то есть в зависимости от выбранного профиля наш провайдер должен отдавать соответствующий LadderEntry . Обновим наш getTimeline(for configuration:, in context:, completion:)
func getTimeline(for configuration: ProfileSelectionIntent, in context: Context, completion: @escaping (Timeline) -> ()) < let entries: [LadderEntry] = [LadderEntry(date: Date(), profile: profile(for: configuration))] let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) >func profile(for configuration: ProfileSelectionIntent) -> Profile < switch configuration.profile < case .lina: return Profile(id: 3, name: "Lina", . ) case .morphling: return Profile(id: 2, name: "Morphling", . ) // . >>
Теперь у виджета появится кнопка Edit Widget и выбор отображаемого профиля для виджета.

Показ Placeholder’a
Когда WidgetKit отображает виджет первый раз, он показывает вью виджета как placeholder. Вью Placeholder view показывает общую структуру вашего виджета, как бы давая пользователю понять, что будет отображено на виджете. WidgetKit вызывает placeholder(in:) у провайдера чтобы получить слепок для placeholder’a.
func placeholder(in context: Context) -> LadderEntry
WidgetKit использует redacted(reason:) модификатор, чтобы показать вью как placeholder.
Для того, чтобы понять, как будет выглядеть наш виджет в данном случае давайте создадим LadderWidgetPlaceholderView .
struct LadderWidgetPlaceholderView: View < var entry: LadderProvider.Entry var body: some View < LadderWidgetEntryView(entry: entry) .redacted(reason: .placeholder) >>
То есть мы просто показываем вью нашего виджета и применяем к нему модификатор .redacted(reason: .placeholder) . Если есть необходимость не показывать какие-то отдельные элементы вью как placeholder, то можно использовать оператор .unredacted() для них.

Более подробно про работу placeholder’ов можно прочитать у Majid Jabrayilov здесь.
Данные для Ladder Widget
Данные для виджета предоставляет LadderProvider , пройдемся более подробно по его функциям.
Плейсхолдер
func placeholder(in context: Self.Context) -> Self.Entry
Тут все просто, просто возвращаем слепок для плейсхолдера.
Таймлайн
func getTimeline(for configuration: Self.Intent, in context: Self.Context, completion: @escaping (Timeline) -> Void)
Как можно заметить этот метод ничего не возвращает, вместо этого у него есть комплишен блок, который принимает объект Timeline .
По сути таймлайн это просто структура, которая содержит массив слепков и объект полиси.
struct Timeline where EntryType : TimelineEntry
Как мы помним, слепок здесь это наша структура LadderEntry , у которой есть date и собственно данные для виджета, так вот эта date и определяет когда виджет будет обновлен в будущем.
Можно например сгенерировать таймлайн, где виджет будет обновляться каждые 3 секунды на протяжении 1 минуты.
func getTimeline(for configuration: ProfileSelectionIntent, in context: Context, completion: @escaping (Timeline) -> ()) < let profile = self.profile(for: configuration) var entries: [LadderEntry] = [LadderEntry(date: Date(), profile: profile)] let threeSeconds: TimeInterval = 3 var currentDate = Date() let endDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)! while currentDate < endDate < let newScore = Double.random(in: 150. 200) let newProfile = Profile(id: profile.id, name: profile.name, rating: profile.rating, score: newScore, imageName: profile.imageName) let entry = LadderEntry(date: currentDate, profile: newProfile) entries.append(entry) currentDate += threeSeconds >let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) >
Что будет когда закончится эта 1 минута? Это зависит от того, что указано в policy объекта структуры TimelineReloadPolicy .
- atEnd — WidgetKit запросит новый таймлайн;
- never — само приложение скажет WidgetKit’у когда обновить виджет;
- after(_ date: ) — определяет точную дату, когда WidgetKit запросит новый таймлайн.
Текущий снапшот
Осталась одна функция в провайдере, которую осталась описать.
func getSnapshot(for configuration: Self.Intent, in context: Self.Context, completion: @escaping (Self.Entry) -> Void)
В ней мы возвращает слепок, который представляет текущее время и состояние виджета. По сути реализация мало чем отличается от getTimeline() , но есть один момент который стоит упомянуть.
WidgetKit вызывает этот метод, когда виджет появляется в разных переходах и так же в галерее виджетов, тогда context.isPreview == true . В этом случае нужно вызвать комплишен как можно быстрее, допускается возвращать заранее приготовленные данные, если загрузка реальных данных может занять больше пары секунд.
func getSnapshot(for configuration: ProfileSelectionIntent, in context: Context, completion: @escaping (LadderEntry) -> ()) < if context.isPreview < let entry = LadderEntry(date: Date(), profile: sampleProfile) completion(entry) >else < // it takes a few seconds to fetch the data let profile = self.profile(for: configuration) let entry = LadderEntry(date: Date(), profile: profile) completion(entry) >>
На симуляторе, это будет выглядеть вот так

Ladder Widget больше фич
WidgetBundle
WidgetKit также предоставляет возможность иметь больше чем один виджета на приложение.
Для того, чтобы добавить еще один виджет в приложение нужно соответственно реализовать этот виджет и создать бандл виджетов, который будет входной точкой для Widget таргета.
Важный момент здесь, что точка входа может быть только одна, то есть @main должен быть только один и стоять перед WidgetsBundle .
@main struct WidgetsBundle: WidgetBundle < @WidgetBundleBuilder var body: some Widget < LadderWidget() NewsWidget() >>
Здесь Xcode может бросить ошибку:
Please specify the widget kind in the scheme’s Environment Variables using the key ‘_XCWidgetKind’ to be one of: ‘LadderWidget’, ‘NewsWidget’>.
Чтобы это поправить нужно пойти Edit Scheme виджет таргета и поправить значение свойства _XCWidgetKind .

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

IntentHandler
Что если, когда мы редактируем виджет мы хотели бы иметь не статические параметры, а динамические? Которые мы могли бы, скажем, загружать с сервера?
Виджеты позволяют это сделать и для этого нужно будет создать Intents Extension таргет, создать файл .intentdefinition и в нем определить опции выбора и далее в классе IntentHandler` обработать колбек выбора опции.
Итак начнем, создаем новый таргет New -> Target -> Intents Extension и даем ему имя например LadderWidgetIntent. Далее руками создаем DynamicLadderIntents.intentdefinition. Его конфигурация будет похожа на LadderIntents.intentdefinition, но с небольшими отличиями.
Вместо Enum у нас будет конкретный тип ProfileType , сам intent будет называться DynamicProfileSelection и так же нужно проставить галочку динамически загружать опции.

Теперь везде в проекте нужно заменить ProfileSelectionIntent на DynamicProfileSelectionIntent .
Xcode автоматически для нас генерирует класс ProfileType , а также протоколы выбора конкретного профиля. Тем самым мы получаем тот самый колбек для загрузки конфигурации.
extension IntentHandler: DynamicProfileSelectionIntentHandling < func provideProfileTypeOptionsCollection(for intent: DynamicProfileSelectionIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) < DispatchQueue.global().asyncAfter(deadline: .now() + 1) < let items: [ProfileType] = [ ProfileType(identifier: "1", display: "Bloodseeker"), ProfileType(identifier: "2", display: "Morphling"), ProfileType(identifier: "3", display: "Lina")] let collection = INObjectCollection(items: items) completion(collection, nil) >> >
Поправляем функцию profile(for _:) в провайдере и теперь наша конфигурация подтягивается динамически.

Передача данных между виджетом и приложением
iOS предоставляет несколько способов передачи данных между виджетом и приложением.
- Keychain access group — хорошо подойдет если нужно передать какой-нибудь сервер-сайд токен, ключ или любую другую сенситив информацию.
- App group — предоставляет больше возможностей, но меньше секьюрити. Можно шарить UserDefaults , а также место на диске.
UserDefaults(suiteName: appGroup)
let url = sharedFileManager.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)
Принудительное обновление виджета
Приложение может обновить свой виджет не дожидаясь, когда это сделает система, с помощью WidgetCenter.
WidgetCenter.shared.reloadAllTimelines()
Еще пару слов
У многих могли возникнуть вопросы по работе с виджетами, попробую ответить на некоторые из них.
Вопрос: Можно ли использовать готовые UIKit вьюшки в виджетах?
Ответ: Нет, виджеты работают только на чистом SwiftUI, даже если вы обернете UIKit вьюшку в SwiftUI вью, то да код скомпилируется, но на устройстве вы увидите просто желтый экран заглушку.
Вопрос: Почему при запуске на симуляторе, я не вижу своих последних изменений?
Ответ: Отладка виджетов достаточно болезненный процесс, то виджет не появляется на экране или появляется только черный квадрат, то вообще виджета нету в галереи виджетов или виджет не обновляется, и такого много, как правило удаление виджета с симулятора и перезапуск симулятора помогает решить такие проблемы.
Заключение
В статье были разобраны основные моменты работы с виджетами, надеюсь кому-то пригодится.
Ссылки
- Apple: Widgets HIG
- Apple: WidgetKit
- WWDC: Widgets Code-along, part 1: The adventure begins
- WWDC: Widgets Code-along, part 2: Alternate timelines
- WWDC: Widgets Code-along, part 3: Advancing timelines
- Swift with Majid: The magic of redacted modifier in SwiftUI
- https://github.com/TikhonovAlexander/Widgets
Как сделать виджет с определенными фото (альбомами) на iPhone
Виджеты, появившиеся на главном экране iPhone с выходом iOS 14 великолепны, однако у некоторых из них все-таки имеются недочеты. В частности, виджет приложения «Фото» вызывает разочарование. Этот инструмент дает приятное ощущение появления любимых фотографий на главном экране рядом со значками приложений. Но, с другой стороны, каждый час картинка меняется случайным образом без какого-либо нашего участия. И хотя изменить поведение самого этого виджета уже нельзя, все еще остается способ получить нужные вам изображения на главном экране.

С момента выхода iOS 14 сторонние разработчики приложений создали немало новых виджетов, которые работают как на главном экране, так и на экране «Сегодня». Многие из них предназначены для одноцелевых приложений. Разработчики с радостью поспешили исправить те нюансы, которые Apple упустила в собственных виджетах. Нам придется обратиться к сторонним приложениям, которые позволят выбирать, какое изображение или изображения вы хотите отображать в виджете на главном экране iPhone и когда.
Видео:
Выберите стороннее приложение для установки виджетов
Когда вы сталкиваетесь с необходимостью выбрать сторонний виджет для демонстрации фотографий, выбор конечно же имеется. Некоторые приложения предоставляют возможности для выбора нескольких изображений, а другие позволяют добавлять текст. Есть даже виджеты, которые накладывают поверх картинки информацию из календаря. Но если вам требуется лишь виртуальная рамка для показа фотографии на главном экране, с большой вероятностью вам подойдет любой виджет такого рода, продвинутый или не очень.
Некоторые из доступных сторонних виджетов для показа фотографий
Custom Widgets – Photo & Text: вы можете использовать всего три изображения, одно из которых будет выведено на виджет. Вы можете вносить изменения в формат показа фотографии, развернув ее, изменив цвет фона или используя вверху аналоговые часы, текст или текущую дату.
Home Photo Widget: вы можете добавить в приложение неограниченное число изображений, а затем создать статический виджет для каждого из них.
Locket – Photo Widgets (99 рублей): вы выбираете альбом для каждого виджета, число изображений, которые вы хотите видеть из него, и как часто виджет должен менять изображения.
Photobox Widget: вы можете использовать виджет трех разных размеров, кроме того виджет позволяет выбрать несколько фотографий, которые случайным образом будут меняться каждые десять минут. Есть возможность добавления сообщения и обрезки фотографий.
PHOTO ALBUM (Photo Widget): для каждого создаваемого виджета формируется свой фотоальбом с любым числом фотографий. Вы можете изменить яркость изображения, периодичность его смены, показать название альбома виджета.
Photo Widget (99 рублей): для виджета вы создаете альбомы, в каждом из которых может храниться до шести фотографий, и вы можете одновременно показывать несколько изображений как по отдельности, так и в виде сетки.
Фото виджет: вы можете добавить одну или несколько фотографий в один виджет (трех разных размеров). Вы можете изменить интервал обновления фотографии, добавить наложение даты или заголовка.
Photo Widget – Pin Photo: вы можете создать виджет как для одного изображения, так и для альбомов, из которых будут выбираться изображения каждую минуту. Вы также можете добавить заголовок каждому виджету.
Photo Widget – Simple: необходимо создать альбомы с любым количеством фотографий, а затем задать виджет для каждой коллекции. В каждом виджете имеется шесть вариантов временного интервала для смены изображений.
Photo Widget – The best one: вы можете добавить одно или несколько изображений к каждому виджету, настроить его для использования одного из ваших фотоальбомов. Фотографии меняются по вашему индивидуальному таймеру. Можно настроить виджет так, чтобы при нажатии на него открывался веб-сайт.
PictureWidget: вы добавляете в приложение сразу пять фотографий. Для виджета домашнего экрана будет отображаться только одно изображение. Для виджета в старом стиле доступны дополнительные параметры настройки.
Все эти приложения в целом работают идентично. В этой статье мы рассмотрим создание фото-виджета на примере работы приложения Фото виджет.
Выберите фотографии для виджета
После того, как вы установите выбранное приложение на свой iPhone, откройте его. Необходимо найти нечто похожее на кнопку «Добавить». В приложении Фото виджет, например, она (Add Album) находится прямо посередине. Нажмите на кнопку и присвойте название создаваемому альбому.

Затем нажмите на кнопку для добавления фотографий в созданный альбом (Add Photos). Откроется окно, в котором вы можете просмотреть все фотографии в приложении «Фото», включая все свои альбомы.
Для выбора фотографии, которую вы хотите использовать, просто коснитесь ее. Если вы выберете несколько изображений, виджет будет циклически менять их, а не отображать статично только одну. Когда вы будете довольны своим выбором, просто нажмите «Добавить».


Отключите «Показывать дату в виджете» (необязательно)
По умолчанию приложение Фото виджет показывает дату при отображении фотографий. Если вам это подходит, переходите к следующему шагу. Однако, если вы хотите, чтобы на главном экране была простая чистая фотография, эту функцию нужно отключить. Откройте в виджете вкладку «Настройки» (Settings) и деактивируйте переключатель рядом с «Показывать дату в виджете» (Show Date in Widget). Кроме того, здесь же можно выбрать интервал для смены фотографий – раздел Photo Refresh Interval.

Добавьте виджет на экран iPhone
Для этого нажмите и удерживайте пальцем на фоне главного экрана, пока не войдете в режим покачивания иконок. Теперь нажмите кнопку «плюс» (+) в верхнем левом углу экрана.

В списке найдите Фото виджет. Он может сразу появиться в качестве предлагаемого виджета, но, если нет, нужно прокрутить вниз и выбрать его из списка.
Как только вы это сделаете, то увидите три предполагаемых размера виджета (маленький, средний и большой). Когда вы определитесь, какой из них подходит, нажмите «Добавить виджет» или перетащите его прямо на домашний экран в нужное место.


- Зеленая, оранжевая или красная точка вверху экрана iOS: для чего они нужны?
- Постучать по крышке Айфона – сделать скриншот: как привязать действия к касанию задней части корпуса iPhone.
- 20 функций iPhone, которые можно отключить большинству пользователей.
