簡體   English   中英

macOS 上的 SwiftUI:帶有詳細視圖和多項選擇的列表

[英]SwiftUI on macOS: list with detail view and multiple selection

TL;博士:

我無法在 macOS 上擁有包含詳細視圖和多項選擇的列表。

更詳細地說:

為了演示我的問題,我做了一個小示例項目。 UI 如下所示: 在此處輸入圖像描述

這是啟動時的“應用程序”,頂部有一個列表,下面有一個詳細表示。 因為我使用的是列表的初始化程序init(_:selection:rowContent:) ,所以selection的類型是Binding<SelectionValue?>? 根據Apple的文檔,我可以免費使用鍵盤箭頭鍵選擇項目。 在此處輸入圖像描述

這是完整的代碼:

import SwiftUI

@main
struct UseCurorsInLisstApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(ViewModel())
        }
    }
}

class ViewModel: ObservableObject {
    @Published var items = [Item(), Item(), Item(), Item(), Item()]
    @Published var selectedItem: Item? = nil
}

struct Item: Identifiable, Hashable {
    let id = UUID()
}

struct ContentView: View {
    @EnvironmentObject var vm: ViewModel
    
    var body: some View {
        VStack {
            
            List(vm.items, id: \.self, selection: $vm.selectedItem) { item in
                VStack {
                    Text("Item \(item.id.uuidString)")
                    Divider()
                }
            }
            
            Divider()
            
            Group {
                if let item = vm.selectedItem {
                    Text("Detail item \(item.id.uuidString)")
                } else {
                    Text("No selection…")
                }
            }
            .frame(minHeight: 200.0, maxHeight: .infinity)
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

現在,到目前為止已經取得了成功,我認為能夠 select 不止一行會很有用,所以我仔細研究了List(_:selection:rowContent:) ,其中selection的類型是Binding<Set<SelectionValue>>? . 為了能夠獲得詳細視圖,我只是對

ViewModel

class ViewModel: ObservableObject {
    @Published var items = [Item(), Item(), Item(), Item(), Item()]
    @Published var selectedItem: Item? = nil
    
    @Published var selectedItems: Set<Item>? = nil {
        didSet {
            if selectedItems?.count == 1, let item = selectedItems?.first {
                selectedItem = item
            }
        }
    }
}

ContentView

struct ContentView: View {
    @EnvironmentObject var vm: ViewModel
    
    var body: some View {
        VStack {
            
            List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
                VStack {
                    Text("Item \(item.id.uuidString)")
                    Divider()
                }
            }
            
            Divider()
            
            Group {
                if vm.selectedItems?.count == 1, let item = vm.selectedItems?.first {
                    Text("Detail item \(item.id.uuidString)")
                } else {
                    Text("No or multiple selection…")
                }
            }
            .frame(minHeight: 200.0, maxHeight: .infinity)
            
        }
    }
}

現在的問題是,我不能再通過單擊或箭頭鍵 select 行中的一個項目。 這是我遇到的限制還是我“持有錯誤”?

使用按鈕並將其插入集合中。 鍵盤選擇也適用於 shift +(向上/向下箭頭)

class ViewModel: ObservableObject {
    @Published var items = [Item(), Item(), Item(), Item(), Item()]
    @Published var selectedItem: Item? = nil
    
    @Published var selectedItems: Set<Item> = []
}

struct ContentView: View {
    @EnvironmentObject var vm: ViewModel
    
    var body: some View {
        VStack {
            
            List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
                Button {
                    vm.selectedItem = item
                    vm.selectedItems.insert(item)
                } label: {
                    VStack {
                        Text("Item \(item.id.uuidString)")
                        Divider()
                    }
                }
                .buttonStyle(PlainButtonStyle())
            }
            
            Divider()
            
            Group {
                if let item = vm.selectedItem {
                    Text("Detail item \(item.id.uuidString)")
                } else {
                    Text("No or multiple selection…")
                }
            }
            .frame(minHeight: 200.0, maxHeight: .infinity)
            
        }
    }
}

添加刪除:

Button {
    vm.selectedItem = item
    if vm.selectedItems.contains(item) {
        vm.selectedItems.remove(item)
    } else {
        vm.selectedItems.insert(item)
    }
}

編輯簡單地需要給一個空白的默認值來設置。 因為在 nil 中它永遠不會 append 設置需要初始化。

@Published var selectedItems: Set<Item> = [] {

實際上我的錯誤非常愚蠢——將selectedItems -set 設置為可選會阻止列表正常工作。 向@Raja Kishan 致敬,他的提議將我推向了正確的方向。

這是完整的工作代碼:

import SwiftUI

@main
struct UseCurorsInLisstApp: App {
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(ViewModel())
        }
    }
}

class ViewModel: ObservableObject {
    @Published var items = [Item(), Item(), Item(), Item(), Item()]
    @Published var selectedItems = Set<Item>()
}

struct Item: Identifiable, Hashable {
    let id = UUID()
}

struct ContentView: View {
    @EnvironmentObject var vm: ViewModel
    
    var body: some View {
        VStack {
            List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
                VStack {
                    Text("Item \(item.id.uuidString)")
                    Divider()
                }
            }
            
            Divider()
            
            Group {
                if vm.selectedItems.count == 1, let item = vm.selectedItems.first {
                    Text("Detail item \(item.id.uuidString)")
                } else {
                    Text("No or multiple selection…")
                }
            }
            .frame(minHeight: 200.0, maxHeight: .infinity)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM