Все, что вам нужно знать о листах

При отображении небольшого фрагмента дополнительной информации на экране важно отображать модальное представление. С UIKit мы могли бы сделать это с presentViewController:animated:completion: функцией.

Однако при использовании SwiftUI нам необходимо изменить наше мышление в сторону использования представления или состояния среды, поскольку модальное представление теперь называется листом.

Давайте посмотрим на это подробнее.

Открыть модальное представление (также известное как лист)

Листы SwiftUI помогают нам показать пользователям модальное представление. sheet - это метод экземпляра Просмотр презентации. В нем описывается, как мы можем отображать наши представления SwiftUI, охватывающие определенные сценарии взаимодействия с пользователем.

Допустим, мы хотим отображать информацию о нашем приложении для пользователей.

Во-первых, нам нужно определить, должно ли приложение отображать модальное представление или нет, привязав его к значению Bool.

Ключевое слово здесь - «следует», потому что, как только мы его отклоняем, значение представленного представления возвращается к false. Это значение оформлено оболочкой свойства @State или может быть получено из ObservableObject ViewModel. Для простоты мы не будем говорить о ViewModels в этом посте.

Во-вторых, нам нужно изменить вид или, в некоторых случаях, состояние среды. Как только мы используем оболочку свойств @State, мы можем просто установить для нее true, а SwiftUI сделает все остальное, чтобы представить модальное представление.

Давайте посмотрим, как это сделать в коде:

Когда мы запускаем приложение, теперь мы можем открыть модальное представление и увидеть подробную информацию:

Программное закрытие модального представления

Пользователи нашего приложения могут просто сдвинуть модальное окно вниз, и оно скроется с красивой анимацией. Установите состояние false, чтобы скрыть это от представления, отвечающего за отображение модального представления.

Теперь, как нам сделать это из самого модального представления? В нашем распоряжении есть два варианта:

  • Используя свойство @Environment presentationMode.
  • Передача состояния в модальное представление в виде привязки.

Использование среды

Оболочка свойств @Environment позволяет нам читать и изменять значения состояния среды просмотра. Чтобы скрыть модальное представление, нам нужно изменить свойство presentationMode. Сначала нам нужно определить нашу точку зрения. Для этого мы добавляем его в свойства модального представления. Чтобы закрыть модальное представление, нам нужно изменить значение, обернутое в режиме презентации:

Этот метод довольно громоздкий, и работа со свойствами окружающей среды может вызвать случайные проблемы, которые трудно отследить и отладить.

Использование привязки

Использование привязки между представлением, которое представляет модальное представление, и самим модальным представлением - это еще один способ скрыть его от кода.

Во-первых, нам нужно добавить новое свойство в структуру модального представления, используя оболочку свойств @Binding. Это означает, что это значение приходит откуда-то за пределами области просмотра.

Теперь, когда мы инициализируем ModalView, нам нужно передать isPresented:

.sheet(isPresented: $showInfoModalView) {
    InfoView(isPresented: $showInfoModalView)
  }

Используя этот подход, мы уверены, что эта переменная принадлежит только этим двум представлениям. Тестировать и отлаживать проще.

Несколько листов в одном представлении SwiftUI

Теперь мы знаем, как представить модальное представление, но как показать несколько модальных представлений?

Представьте, что мы хотели бы представить информацию о приложении и представлении настроек из основного представления приложения.

Мы можем сделать это, используя эти два подхода:

  • Использование нескольких листов, представляющих функции.
  • Использование перечисления Identifiable для сохранения текущего состояния отображаемого листа.

Несколько функций листа в одном представлении SwiftUI

Мы можем прикрепить функцию sheet к любому представлению или элементу управления SwiftUI (например, к Button):

Две кнопки - это нормально, но, допустим, у нас их больше. Это может стать довольно запутанным, поэтому нам придется иметь дело со многими @State переменными.

Использование перечисления всех модальных представлений

Если мы посмотрим на официальную документацию Apple, есть еще одна функция для отображения листа. Попробуем использовать.

Сначала мы определим enum со всеми параметрами модального представления:

enum Sheet: Identifiable {
    case info
    case settings
  }

Теперь мы можем использовать это в представлении SwiftUI. Нам нужна новая переменная @State с необязательным типом Sheet, и мы будем использовать ее, чтобы определить, какое модальное представление мы хотим представить:

Нам не нужно останавливаться на достигнутом. Мы можем избавиться от беспорядка в этом коде, добавив вычисляемое свойство в перечисление Sheet:

Затем мы можем использовать его при открытии листа:

.sheet(item: $activeSheet) { $0.modalView }

Используя новые причудливые функции keypaths в замыканиях, мы можем упростить это еще больше:

.sheet(item: $activeSheet, content: \.modalView)

Одно из предостережений в отношении этого подхода заключается в том, что нам нужно изменить часть нашего процесса, чтобы скрыть представление от кода. Для этого мы установили nil вместо false.

Этот подход намного безопаснее, потому что мы используем тип перечисления, чтобы все было хорошо организовано.

Давайте посмотрим на это в действии.

TL;DR

Модальные представления в SwiftUI представлены с использованием модификатора sheet для представления или элемента управления. Самый простой способ - иметь свойство @State, указывающее, когда оно должно быть видимым.

Чтобы скрыть модальное представление, мы можем использовать параметр среды или передать привязку к объекту модального представления. Отображение нескольких листов может быть достигнуто либо с помощью нескольких модификаторов листов, либо с помощью объекта со всеми возможными перечислениями модальных представлений.

Ресурсы