SwiftUI на macOS: как включить пользовательский интерфейс для onDelete (удаление из списка) - PullRequest
0 голосов
/ 16 января 2020

Возможно, я особенно плотно этим утром, но я пытаюсь удалить строку из List в SwiftUI на macOS.

Проблема заключается в том, что нет никакого пользовательского интерфейса, доступного для выполнения удаления. Под этим я подразумеваю, что List не отвечает на нажатия клавиш удаления, не имеет меню для щелчка правой кнопкой мыши и не поддерживает другие жесты, такие как пролистывание для удаления (что в любом случае было бы странным для macOS).

Вот пример Я использую:

import SwiftUI

struct ContentView: View {
    @State var items = ["foo", "bar", "baz"]
    @State var selection: String? = nil

    var body: some View {
        List(selection: $selection) {
            ForEach(items, id: \.self) { Text($0) }
                .onDelete { self.items.remove(atOffsets: $0)}
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Точно такой же код на iOS дает мне табличное представление со стандартным интерфейсом «проведите пальцем влево для удаления». В macOS просто ничего нет.

Я пытался добавить

    .onDeleteCommand(perform: {
        if let sel = self.selection, let idx = self.items.firstIndex(of: sel) {
            self.items.remove(at: idx)
        }
    })

к List, но по-прежнему нет ответа на нажатие клавиши удаления.

Как включить List удаление строки в macOS?

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

Этот код включает меню «Удалить» и удаляет выбранный элемент, когда я выбираю «Правка»> «Удалить» (без ручного подключения меню):

struct ContentView: View {
    @State var items = ["foo", "bar", "baz"]
    @State var selection: String? = nil

    var body: some View {
        List(selection: $selection) {
            ForEach(items, id: \.self) { Text($0) }
        }
        .onDeleteCommand {
            if
                let sel = self.selection,
                let idx = self.items.firstIndex(of: sel) {
                print("delete item: \(sel)")
                self.items.remove(at: idx)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .animation(.default)
    }
}

Затем нажмите клавишу , чтобы удалить работайте, сделайте его клавиатурным эквивалентом для пункта меню «Удалить»: - «Редактировать главную панель» - выберите «Правка»> «Удалить» - щелкните в поле «Эквивалент ключа» - нажмите клавишу удаления.

enter image description here

Запустите приложение, выберите элемент, нажмите клавишу удаления, и ваш элемент должен исчезнуть.

0 голосов
/ 16 января 2020

Я нашел довольно запутанное решение для этого, и я надеюсь, что есть лучший способ.

Я сделал следующее:

  • Подключите действие к существующему Команда «Удалить»
  • Создать «ObservableObject» Menu, который публикует выбранные команды меню
  • Передать издателю ContentView, чтобы он мог подписаться и действовать в соответствии с изменениями

Вот два соответствующих файла:

Сначала AppDelegate.swift:

enum MenuCommand {
    case none
    case delete
}

class Menu: ObservableObject {
    @Published var item: MenuCommand = .none
}


@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!
    @ObservedObject var menu = Menu()

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView(menu: menu)

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    @IBAction func delete(_ sender: Any) {
        print("delete menu")
        menu.item = .delete
    }

}

и ContentView.swift:

import SwiftUI

struct ContentView: View {
    @ObservedObject var menu: Menu
    @State var items = ["foo", "bar", "baz"]
    @State var selection: String? = nil

    var body: some View {
        List(selection: $selection) {
            ForEach(items, id: \.self) { Text($0) }
        }
        .onReceive(
            self.menu.objectWillChange
                .receive(on: RunLoop.main)) { _ in
            if
                case .delete = self.menu.item,
                let sel = self.selection,
                let idx = self.items.firstIndex(of: sel) {
                print("delete item: \(sel)")
                self.items.remove(at: idx)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .animation(.default)
    }
}

Примечание: don не забудьте подключить пункт меню «Удалить» к IBAction.

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