7

有没有办法禁用特定的选择器项目?在 AppKit 中,您可以NSPopUpButton通过协议禁用项目NSMenuValidation,但可以预见的是,禁用选择器中的标签无济于事。只是 SwiftUI 中的另一个 API 缺口?

我试过了:

Picker(selection: $viewModel.providerSelection, label: Text("Try using:")) {
    ForEach(0..<Provider.allCases.count) {
        Text(Provider.allCases[$0].rawValue.capitalized)
            .disabled(true)
    }
}

并且禁用和不在这里之间没有视觉或交互差异。

4

1 回答 1

1

这似乎目前在纯 SwiftUI 中不支持。但是,您可以尝试换行NSPopUpButtonNSViewRepresentable如下所示:

    /// SwiftUI wrapper for NSPopUpButton which allows items to be disabled, which is currently not supported in SwiftUI's Picker
struct PopUpButtonPicker<Item: Equatable>: NSViewRepresentable {

    final class Coordinator: NSObject {
        private let parent: PopUpButtonPicker

        init(parent: PopUpButtonPicker) {
            self.parent = parent
        }

        @IBAction
        func selectItem(_ sender: NSPopUpButton) {
            let selectedItem = self.parent.items[sender.indexOfSelectedItem]
            print("selected item \(selectedItem) at index=\(sender.indexOfSelectedItem)")
            self.parent.selection = selectedItem
        }
    }

    let items: [Item]
    var isItemEnabled: (Item) -> Bool = { _ in true }
    @Binding var selection: Item
    let titleProvider: (Item) -> String

    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeNSView(context: Self.Context) -> NSPopUpButton {
        let popUpButton = NSPopUpButton(frame: .zero, pullsDown: false)
        popUpButton.autoenablesItems = false
        popUpButton.target = context.coordinator
        popUpButton.action = #selector(Coordinator.selectItem(_:))

        for item in items.enumerated() {
            popUpButton.addItem(withTitle: self.titleProvider(item.element))
            // in order for this to work, autoenablesItems must be set to false
            popUpButton.menu?.item(at: item.offset)?.isEnabled = self.isItemEnabled(item.element)
        }

        if let selectedIndex = self.items.firstIndex(where: { $0 == self.selection }) {
            popUpButton.selectItem(at: selectedIndex)
        }

        return popUpButton
    }

    func updateNSView(_ view: NSPopUpButton, context: Self.Context) { }
}


// MARK: - Usage

struct ContentView: View {

    private let items: [Int] = [1, 2, 3, 4, 5]
    @State private var selectedValue: Int = 0

    var body: some View {
        PopUpButtonPicker(items: self.items, isItemEnabled: { $0 != 4 }, selection: self.$selectedValue, titleProvider: String.init)
    }
}
于 2022-01-26T08:52:00.610 回答