Программирование
Как использовать UIContentUnavailableConfiguration для управления пустыми состояниями
Мне очень нравится это улучшение в UIKit, оно затрагивает аспект, которым долгое время пренебрегали разработчики и дизайнеры — пустое состояние.
В этом году на WWDC Apple удивила разработчиков неожиданным улучшением UIKit. Представление UIContentUnavailableConfiguration было направлено на упрощение процесса создания пустых состояний для контроллеров представления.
По словам Apple, UIContentUnavailableConfiguration представляет собой composable описание пустого состояния и может быть снабжено содержимым-заполнителем, например, изображением или текстом.
Вот пример пустого состояния, продемонстрированный на WWDC:
Теперь давайте разберемся в деталях.
Примечание: Эта статья в основном посвящена UIKit. Если вы хотите узнать, как сделать то же самое в SwiftUI, рекомендую ознакомиться с этой статьей Антуана ван дер Ли.
Создание UIContentUnavailableConfiguration
Существует 4 способа создания UIContentUnavailableConfiguration:
- Создание с нуля
- Использование предопределенной конфигурации загрузки
- Использование предопределенной конфигурации поиска
- Использование конфигурации UIHostingConfiguration
1. Создание с нуля
Чтобы начать с нуля, мы должны сначала создать пустую UIContentUnavailableConfiguration.
var config = UIContentUnavailableConfiguration.empty()
После этого нам нужно будет настроить содержимое UIContentUnavailableConfiguration в соответствии с нашими потребностями:
config.image = UIImage(systemName: "applelogo") config.text = "WWDC23 Demo" config.secondaryText = "Code new worlds."
Наконец, просто установить конфигурацию в contentUnavailableConfiguration контроллера представления.
self.contentUnavailableConfiguration = config
Пустое состояние, показанное ниже, теперь должно быть видно в центре контроллера представления.
Вы можете обратиться к документации по UIContentUnavailableConfiguration, чтобы узнать обо всех других настраиваемых параметрах содержимого.
2. Использование предопределенной конфигурации загрузки
Если нам нужно показать пустое состояние в ожидании загрузки приложений, то мы можем использовать предопределенную конфигурацию загрузки.
var config = UIContentUnavailableConfiguration.loading() self.contentUnavailableConfiguration = config
Использование приведенного выше кода приведет к следующему пустому состоянию:
Как и в пустой конфигурации, содержимое заполнителя загрузочной конфигурации также настраивается.
var config = UIContentUnavailableConfiguration.loading() config.text = "Fetching content. Please wait..." config.textProperties.font = .boldSystemFont(ofSize: 18) self.contentUnavailableConfiguration = config
Вот как это выглядит после вышеуказанной настройки:
3. Использование предопределенной конфигурации поиска
Еще одна очень полезная предопределенная конфигурация — это конфигурация поиска. Мы можем использовать ее, когда хотим показать пустое состояние для результата поиска:
var config = UIContentUnavailableConfiguration.search() self.contentUnavailableConfiguration = config
Подобно конфигурации загрузки, содержимое-заполнитель конфигурации поиска также можно настраивать.
4. Использование UIHostingConfiguration
И наконец, мой личный фаворит — использование UIHostingConfiguration. Этот подход, по сути, позволяет нам создать любой пустой макет состояния, который мы хотим, используя SwiftUI.
Например:
let config = UIHostingConfiguration { Text("Unknown error occurred, please [contact support](https://swiftsenpai.com).") .multilineTextAlignment(.center) } self.contentUnavailableConfiguration = config
Приведенный выше код даст нам следующий результат:
Профессиональный совет: Чтобы узнать больше о UIHostingConfiguration, я рекомендую ознакомиться с этими статьями.
Обновление contentUnavailableConfiguration контроллера представления
Когда дело доходит до обновления contentUnavailableConfiguration, Apple рекомендует разработчикам переопределить новый метод обновления под названием updateContentUnavailableConfiguration(using:).
На данный момент нет официальной документации, определяющей, когда именно будет вызываться этот метод. Однако, по моим наблюдениям, метод вызывается каждый раз, когда загружается контроллер представления.
В ситуациях, когда нам нужно вручную вызвать метод обновления, мы можем вызвать следующую функцию:
setNeedsUpdateContentUnavailableConfiguration()
Пример использования в реальной жизни
На основе того, что мы только что обсудили, я создал пример приложения, чтобы показать, как использовать UIContentUnavailableConfiguration для отображения пустого состояния, когда приложение либо загружается, либо сталкивается с ошибкой.
Для дальнейшего повышения интерактивности примера приложения я также добавил кнопку перезагрузки (которая также является частью UIContentUnavailableConfiguration) в пустое состояние ошибки. Эта кнопка перезагрузки позволяет пользователям легко обновить содержимое приложения в случае ошибки.
Вот полный код примера, если вам интересно. Обязательно запустите его на Xcode 15 beta 1 или более поздней версии.
import UIKit class ContentUnavailableViewController: UIViewController { /// Variable to keep track of content fetching state /// nil means content is not yet fetched var fetchContentSuccessful: Bool? = nil override func viewDidLoad() { super.viewDidLoad() // Create fetch button let fetchAction = UIAction(handler: { [weak self]_ in self?.startFetchCotent() }) let fetchButton = UIBarButtonItem(title: "Fetch", primaryAction: fetchAction) navigationItem.rightBarButtonItem = fetchButton } override func updateContentUnavailableConfiguration( using state: UIContentUnavailableConfigurationState ) { // Remove existing configuration (if exist) contentUnavailableConfiguration = nil guard let fetchContentSuccessful else { // User have not trigger fetch return } if fetchContentSuccessful { // Prompt alert view showContent() } else { // Show empty state showError() } } /// Start the fetch content flow private func startFetchCotent() { Task { [weak self] in guard let self = self else { return } showLoading() fetchContentSuccessful = await fetchContent() // Update UI setNeedsUpdateContentUnavailableConfiguration() } } /// Action to run after successfully fetch content private func showContent() { let alert = UIAlertController( title: "🎉🎉🎉", message: "Fetch successful!", preferredStyle: .alert ) let positiveAction = UIAlertAction( title: "OK", style: .default ) alert.addAction(positiveAction) present(alert, animated: true) } /// Show the loading empty state private func showLoading() { var config = UIContentUnavailableConfiguration.loading() config.text = "Fetching content. Please wait..." config.textProperties.font = .boldSystemFont(ofSize: 18) self.contentUnavailableConfiguration = config } /// Show the empty state when encounter error private func showError() { var errorConfig = UIContentUnavailableConfiguration.empty() errorConfig.image = UIImage(systemName: "exclamationmark.circle.fill") errorConfig.text = "Something went wrong." errorConfig.secondaryText = "Please try again later." // Create configuration for reload button var retryButtonConfig = UIButton.Configuration.borderless() retryButtonConfig.image = UIImage(systemName: "arrow.clockwise.circle.fill") errorConfig.button = retryButtonConfig // Define the reload button action errorConfig.buttonProperties.primaryAction = UIAction.init(handler: { _ in Task { [weak self] in guard let self = self else { return } startFetchCotent() } }) contentUnavailableConfiguration = errorConfig } /// A dummy function to simulate the fetch content action private func fetchContent() async -> Bool { // Sleep for 1 minutes to simulate a slow API call try? await Task.sleep(nanoseconds: 1_000_000_000) return Bool.random() } }
Подведение итогов
Мне очень нравится это улучшение в UIKit, оно затрагивает аспект, которым долгое время пренебрегали разработчики и дизайнеры — пустое состояние.
Уменьшая трение, связанное с обработкой пустых состояний, Apple эффективно устраняет одно из распространенных оправданий, по которым разработчики пренебрегали этим аспектом дизайна приложений. Компания поощряет разработчиков брать на себя ответственность за то, чтобы пользовательский интерфейс их приложений не оставался в унылом, необработанном состоянии.
Спасибо за чтение. 👨🏻💻
-
Видео и подкасты для разработчиков1 месяц назад
Особенности сервиса Яндекс Про и будущее Flutter
-
Исследования1 месяц назад
Результаты опроса разработчиков Stack Overflow 2024
-
Видео и подкасты для разработчиков1 месяц назад
Вам не нужно хранилище в приложении
-
Видео и подкасты для разработчиков1 месяц назад
Нужно ли учить Java для Android-разработки в 2024