Контекстные меню в
SwiftUI это мощный инструмент для скрытия дополнительных действий и функций. Однако они часто страдают от недостатка контекста: пользователь не всегда понимает, к чему именно относится действие, пока не нажмет на него. Начиная с
iOS 16,
SwiftUI предлагает решение этой проблемы с помощью модификатора
preview, который позволяет показывать детальную информацию прямо в меню, прежде чем пользователь сделает выбор.
Базовый пример - уточнение действия:
Рассмотрим сценарий с просмотром документа. Без
preview пользователь видит только действия, но не понимает, какой именно документ будет затронут:
DocumentCard(document: report)
.contextMenu {
Button("Переименовать", systemImage: "pencil") {
rename()
}
Button("Создать копию", systemImage: "doc.on.doc") {
duplicate()
}
Button("Удалить", systemImage: "trash", role: .destructive) {
delete()
}
}
С добавлением
preview меню становится самодостаточным:
DocumentCard(document: report)
.contextMenu {
Button("Переименовать", systemImage: "pencil") {
rename()
}
Button("Создать копию", systemImage: "doc.on.doc") {
duplicate()
}
Button("Удалить", systemImage: "trash", role: .destructive) {
delete()
}
} preview: {
// Preview показывает, с каким документом работаем
VStack(alignment: .leading, spacing: 8) {
Text(report.title)
.font(.headline)
HStack {
Label("\(report.pageCount) стр.", systemImage: "doc.text")
Label(report.formattedDate, systemImage: "calendar")
}
.font(.caption)
.foregroundStyle(.secondary)
if let previewText = report.preview {
Text(previewText)
.font(.caption)
.lineLimit(3)
.foregroundStyle(.secondary)
}
}
.padding()
.frame(width: 300)
}
Расширенный сценарий - интерактивный preview:
Модификатор
preview поддерживает не только статический контент, но и интерактивные элементы, что открывает дополнительные возможности:
Image(uiImage: selectedPhoto)
.resizable()
.aspectRatio(contentMode: .fit)
.contextMenu {
Button("Редактировать", systemImage: "slider.horizontal.3") {
editPhoto()
}
Button("Поделиться", systemImage: "square.and.arrow.up") {
sharePhoto()
}
Button("Удалить", systemImage: "trash", role: .destructive) {
deletePhoto()
}
} preview: {
// Preview с возможностью масштабирования
ZoomableImageView(image: selectedPhoto)
.frame(height: 300)
.cornerRadius(12)
}
Важные детали:
- Preview работает только в контекстных меню, вызванных долгим нажатием.
- Размер и layout preview можно гибко настраивать.
- Preview поддерживает анимации и переходы внутри себя.
- Может содержать любые SwiftUI вью, включая списки, сетки и интерактивные элементы.
Оптимизация производительности:
Поскольку
preview рендерится в момент появления меню, стоит избегать тяжелых операций в его инициализации. Для динамических данных лучше использовать отложенную загрузку или кэширование.
Вывод:
Модификатор
preview для контекстных меню - это не просто косметическое улучшение, а фундаментальное изменение подхода к проектированию контекстных действий. Он позволяет превратить меню из простого списка команд в информативный интерфейсный элемент, который показывает пользователю ровно ту информацию, которая нужна для принятия осознанного решения.