Программирование
Как использовать UIContentUnavailableConfiguration для управления пустыми состояниями
Мне очень нравится это улучшение в UIKit, оно затрагивает аспект, которым долгое время пренебрегали разработчики и дизайнеры — пустое состояние.
В этом году на WWDC Apple удивила разработчиков неожиданным улучшением UIKit. Представление UIContentUnavailableConfiguration было направлено на упрощение процесса создания пустых состояний для контроллеров представления.
По словам Apple, UIContentUnavailableConfiguration представляет собой composable описание пустого состояния и может быть снабжено содержимым-заполнителем, например, изображением или текстом.
Вот пример пустого состояния, продемонстрированный на WWDC:
Теперь давайте разберемся в деталях.
Примечание: Эта статья в основном посвящена UIKit. Если вы хотите узнать, как сделать то же самое в SwiftUI, рекомендую ознакомиться с этой статьей Антуана ван дер Ли.
Создание UIContentUnavailableConfiguration
Существует 4 способа создания UIContentUnavailableConfiguration:
- Создание с нуля
- Использование предопределенной конфигурации загрузки
- Использование предопределенной конфигурации поиска
- Использование конфигурации UIHostingConfiguration
1. Создание с нуля
Чтобы начать с нуля, мы должны сначала создать пустую UIContentUnavailableConfiguration.
var config = UIContentUnavailableConfiguration.empty()
После этого нам нужно будет настроить содержимое UIContentUnavailableConfiguration в соответствии с нашими потребностями:
xxxxxxxxxx
config.image = UIImage(systemName: "applelogo")
config.text = "WWDC23 Demo"
config.secondaryText = "Code new worlds."
Наконец, просто установить конфигурацию в contentUnavailableConfiguration контроллера представления.
xxxxxxxxxx
self.contentUnavailableConfiguration = config
Пустое состояние, показанное ниже, теперь должно быть видно в центре контроллера представления.
Вы можете обратиться к документации по UIContentUnavailableConfiguration, чтобы узнать обо всех других настраиваемых параметрах содержимого.
2. Использование предопределенной конфигурации загрузки
Если нам нужно показать пустое состояние в ожидании загрузки приложений, то мы можем использовать предопределенную конфигурацию загрузки.
xxxxxxxxxx
var config = UIContentUnavailableConfiguration.loading()
self.contentUnavailableConfiguration = config
Использование приведенного выше кода приведет к следующему пустому состоянию:
Как и в пустой конфигурации, содержимое заполнителя загрузочной конфигурации также настраивается.
xxxxxxxxxx
var config = UIContentUnavailableConfiguration.loading()
config.text = "Fetching content. Please wait..."
config.textProperties.font = .boldSystemFont(ofSize: 18)
self.contentUnavailableConfiguration = config
Вот как это выглядит после вышеуказанной настройки:
3. Использование предопределенной конфигурации поиска
Еще одна очень полезная предопределенная конфигурация — это конфигурация поиска. Мы можем использовать ее, когда хотим показать пустое состояние для результата поиска:
xxxxxxxxxx
var config = UIContentUnavailableConfiguration.search()
self.contentUnavailableConfiguration = config
Подобно конфигурации загрузки, содержимое-заполнитель конфигурации поиска также можно настраивать.
4. Использование UIHostingConfiguration
И наконец, мой личный фаворит — использование UIHostingConfiguration. Этот подход, по сути, позволяет нам создать любой пустой макет состояния, который мы хотим, используя SwiftUI.
Например:
xxxxxxxxxx
let config = UIHostingConfiguration {
Text("Unknown error occurred, please [contact support](https://swiftsenpai.com).")
.multilineTextAlignment(.center)
}
self.contentUnavailableConfiguration = config
Приведенный выше код даст нам следующий результат:
Профессиональный совет: Чтобы узнать больше о UIHostingConfiguration, я рекомендую ознакомиться с этими статьями.
Обновление contentUnavailableConfiguration контроллера представления
Когда дело доходит до обновления contentUnavailableConfiguration, Apple рекомендует разработчикам переопределить новый метод обновления под названием updateContentUnavailableConfiguration(using:).
На данный момент нет официальной документации, определяющей, когда именно будет вызываться этот метод. Однако, по моим наблюдениям, метод вызывается каждый раз, когда загружается контроллер представления.
В ситуациях, когда нам нужно вручную вызвать метод обновления, мы можем вызвать следующую функцию:
xxxxxxxxxx
setNeedsUpdateContentUnavailableConfiguration()
Пример использования в реальной жизни
На основе того, что мы только что обсудили, я создал пример приложения, чтобы показать, как использовать UIContentUnavailableConfiguration для отображения пустого состояния, когда приложение либо загружается, либо сталкивается с ошибкой.
Для дальнейшего повышения интерактивности примера приложения я также добавил кнопку перезагрузки (которая также является частью UIContentUnavailableConfiguration) в пустое состояние ошибки. Эта кнопка перезагрузки позволяет пользователям легко обновить содержимое приложения в случае ошибки.
Вот полный код примера, если вам интересно. Обязательно запустите его на Xcode 15 beta 1 или более поздней версии.
xxxxxxxxxx
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 эффективно устраняет одно из распространенных оправданий, по которым разработчики пренебрегали этим аспектом дизайна приложений. Компания поощряет разработчиков брать на себя ответственность за то, чтобы пользовательский интерфейс их приложений не оставался в унылом, необработанном состоянии.
Спасибо за чтение. 👨🏻💻
-
Новости2 недели назад
Видео и подкасты о мобильной разработке 2025.14
-
Видео и подкасты для разработчиков4 недели назад
Javascript для бэкенда – отличная идея: Node.js, NPM, Typescript
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.12
-
Разработка3 недели назад
«Давайте просто…»: системные идеи, которые звучат хорошо, но почти никогда не работают