Онлайн курсы по Swift

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn
Share on pinterest
Pinterest
Share on vk
VK
Share on odnoklassniki
OK
Share on telegram
Telegram
Share on whatsapp
WhatsApp

SwiftUI: как создать контекстное меню в iOS 13

Ранее Apple официально выпустила iOS 13 для широкой публики. Помимо темного режима и других новых функций, последняя версия iOS также представляет нам новый способ, известный как контекстное меню, для взаимодействия с устройством.

Контекстное меню похоже на просмотр в 3D Touch. Одно заметное отличие заключается в том, что эта функция работает на всех устройствах под управлением iOS 13 и более поздних версий, даже если устройство не поддерживает 3D Touch. Чтобы вызвать контекстное меню, люди используют жест касания и удержания или принудительное касание, если устройство работает от 3D Touch.

Если вы обновились до iOS 13, вы можете найти этот новый элемент управления в большинстве стандартных приложений, таких как Карты и Фотографии.

В этом уроке давайте посмотрим, как реализовать контекстное меню в SwiftUI.

Важно: у вас должен быть Xcode 11 и macOS Catalina (v10.15), чтобы работать дальше.

Создание контекстного меню в SwiftUI

Для начала загрузите этот стартовый проект — SwiftUIListStarter и разархивируйте его на своем Mac. После открытия SwiftUIList.xcodeproj файла запустите проект или просмотрите его. Приложение должно показать вам список ресторанов.

 

Что мы собираемся сделать — это создать контекст для этого демонстрационного приложения. Мы хотим вызвать контекстное меню, когда люди касаются и удерживают любую из строк. В меню предусмотрены две кнопки действий, которые пользователи могут выбрать: «Удалить» и «Избранное». Когда выбрано, кнопка «Удалить» удалит строку из списка. Кнопка «Избранное» помечает выбранную строку звездочкой.

Работа с модификатором ContextMenu

SwiftUI сделал очень простым создание контекстного меню. Вам просто нужно прикрепить contextMenu контейнер к представлению и настроить его пункты меню.

Чтобы представить эти два элемента в контекстном меню, мы можем прикрепить contextMenu каждую строку в списке следующим образом:

List {
    ForEach(restaurants) { restaurant in
        BasicImageRow(restaurant: restaurant)
            .contextMenu {
                
                Button(action: {
                    // delete the selected restaurant
                }) {
                    HStack {
                        Text("Delete")
                        Image(systemName: "trash")
                    }
                }
                
                Button(action: {
                    // mark the selected restaurant as favorite
                }) {
                    HStack {
                        Text("Favorite")
                        Image(systemName: "star")
                    }
                }
            }
    }
}

Реализация действий кнопки

В данный момент мы не реализовали ни одно из действий кнопок. Однако, если вы запустите приложение, оно вызовет контекстное меню, когда вы дотронетесь до одной из строк и удерживаете ее.
Теперь давайте продолжим реализовывать действие удаления. В отличие от onDelete обработчика, contextMenu не дает нам индекс выбранного ресторана. Чтобы понять это, потребуется немного работы. Создать новую функцию в ContentView:

private func delete(item restaurant: Restaurant) {
    if let index = self.restaurants.firstIndex(where: { $0.id == restaurant.id }) {
        self.restaurants.remove(at: index)
    }
}

Эта delete функция принимает объект ресторана и ищет его индекс в restaurants массиве. Чтобы найти индекс, мы вызываем firstIndex функцию и указываем критерии поиска. Функция выполняет цикл по массиву и сравнивает идентификатор данного ресторана с идентификаторами в массиве. Если есть совпадение, firstIndex функция возвращает индекс данного ресторана. Получив индекс, мы можем удалить ресторан из restaurants массива, вызвав его remove(at:).

Затем вставьте следующую строку кода под // delete the selected restaurant:

self.delete(item: restaurant)

Мы просто вызываем delete функцию, когда пользователи выбирают кнопку Удалить .

Чтобы удалить удаление, нам также нужно пометить restaurantsмассив @State ключевым словом:

@State var restaurants = [ ... ]

Теперь мы готовы протестировать приложение. Нажмите кнопку Play, чтобы запустить приложение. Нажмите и удерживайте одну из строк, чтобы вызвать контекстное меню. Выберите «Удалить», и вы увидите, что выбранный вами ресторан удален из списка.

Давайте перейдем к реализации кнопки «Избранное». Когда эта кнопка выбрана, приложение поместит звезду в выбранный ресторан. Структура Restaurant уже имеет свойство с именем, isFavorite которое указывает, отмечен ли ресторан как любимый. По умолчанию его значение установлено на false.

struct Restaurant: Identifiable {
    var id = UUID()
    var name: String
    var image: String
    var isFavorite: Bool = false
}

Подобно функции удаления , мы создадим отдельную функцию ContentView для настройки любимого ресторана. Вставьте следующий код, чтобы создать новую функцию:

private func setFavorite(item restaurant: Restaurant) {
    if let index = self.restaurants.firstIndex(where: { $0.id == restaurant.id }) {
        self.restaurants[index].isFavorite.toggle()
    }
}

Код очень похож на код delete функции. Сначала мы узнаем индекс данного ресторана. Как только у нас есть индекс, мы меняем значение его isFavorite свойства. Здесь мы вызываем toggle функцию для переключения значения. Скажем, например, если исходное значение isFavorite установлено в false, значение изменится на true после вызова toggle().

Далее мы должны обработать пользовательский интерфейс строки. Всякий раз, когда isFavorite свойство ресторана установлено на true, строка должна представлять звездный индикатор. Обновите BasicImageRow структуру следующим образом:

struct BasicImageRow: View {
    var restaurant: Restaurant
 
    var body: some View {
        HStack {
            Image(restaurant.image)
                .resizable()
                .frame(width: 40, height: 40)
                .cornerRadius(5)
            Text(restaurant.name)
 
            if restaurant.isFavorite {
                Spacer()
 
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }
        }
    }
}

В приведенном выше коде мы просто добавляем фрагмент кода в HStack. Если isFavorite свойство данного ресторана установлено на true, мы добавляем в строку разделитель и образ системы.

Вот так мы реализуем фаворитную функцию. Наконец, вставьте следующую строку кода в, // mark the selected restaurant as favorite чтобы вызвать setFavorite функцию:

self.setFavorite(item: restaurant)

Теперь пришло время проверить. Запустите приложение на холсте. Нажмите и удерживайте одну из строк (например, «Маленькая устрица»), а затем выберите «Избранное». Вы должны увидеть приложение звезды, появившееся в конце ряда.

 

Вот как вы реализуете контекстные меню в SwiftUI. Я надеюсь, вам понравился этот урок. Мы собираемся выпустить наш новый курс о SwiftUI в скором времени. Пожалуйста, следите за обновлениями.

👉Хочешь больше новостей из мира Swift и iOS разработки?
❤️ Лайк и подписка на @swiftlab приветствуются.

Пролистать наверх