Реалізація Context Menu для iOS-програми
Context Menu в iOS 13+ — це UIMenu + UIContextMenuInteraction. Правильно реалізоване контекстне меню однаково працює при довгому натиску на Haptic Touch пристроях, при натиску з силою на 3D Touch пристроях, та при правому кліку на iPad з трекпадом або Magic Mouse.
UIContextMenuInteraction для довільного View
class CardView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
let interaction = UIContextMenuInteraction(delegate: self)
addInteraction(interaction)
}
}
extension CardView: UIContextMenuInteractionDelegate {
func contextMenuInteraction(
_ interaction: UIContextMenuInteraction,
configurationForMenuAtLocation location: CGPoint
) -> UIContextMenuConfiguration? {
UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { [weak self] _ in
guard let self = self else { return nil }
let open = UIAction(title: "Відкрити", image: UIImage(systemName: "arrow.up.right")) { _ in
self.handleOpen()
}
let copy = UIAction(title: "Копіювати", image: UIImage(systemName: "doc.on.doc")) { _ in
self.handleCopy()
}
let delete = UIAction(
title: "Видалити",
image: UIImage(systemName: "trash"),
attributes: .destructive
) { _ in
self.handleDelete()
}
// Групування через UIMenu
let editMenu = UIMenu(title: "", options: .displayInline, children: [copy])
return UIMenu(title: "", children: [open, editMenu, delete])
}
}
}
options: .displayInline для вкладеного UIMenu убирає заголовок підгрупи та візуально розділяє пункти горизонтальною лінією — стандартний паттерн розділення деструктивних дій від безпечних.
SwiftUI .contextMenu
struct ItemView: View {
var item: Item
var body: some View {
ItemCard(item: item)
.contextMenu {
Button {
openItem(item)
} label: {
Label("Відкрити", systemImage: "arrow.up.right")
}
Button(role: .destructive) {
deleteItem(item)
} label: {
Label("Видалити", systemImage: "trash")
}
} preview: {
ItemPreviewView(item: item)
.frame(width: 300, height: 200)
}
}
}
preview: у SwiftUI — preview при довгому натиску, аналог previewProvider у UIKit. Button(role: .destructive) автоматично фарбує пункт в червоний.
UITableView та UICollectionView
Спеціалізовані методи делегата без необхідності додавати UIContextMenuInteraction вручну:
// UITableView
func tableView(_ tableView: UITableView,
contextMenuConfigurationForRowAt indexPath: IndexPath,
point: CGPoint) -> UIContextMenuConfiguration? {
// ...
}
// UICollectionView
func collectionView(_ collectionView: UICollectionView,
contextMenuConfigurationForItemsAt indexPaths: [IndexPath],
point: CGPoint) -> UIContextMenuConfiguration? {
// iOS 16+ підтримує множественний вибір
}
Ориентири по срокам
Контекстне меню для одного типу View або ячейки — кілька годин. Повноцінна реалізація для UITableView/UICollectionView з preview та кастомними діями — 1 робочий день.







