【问题标题】:Get selected item in SwiftUI list without using a navigation link在不使用导航链接的情况下获取 SwiftUI 列表中的选定项目
【发布时间】:2021-08-09 18:49:15
【问题描述】:

我正在编写一个类似于看板的 SwiftUI Mac 应用程序。该应用程序具有三个列表:Todo、Doing 和 Done。每个列表的底部是一个按钮,用于将任务移动到另一个列表。例如,待办事项列表有一个开始执行按钮。从待办事项列表中选择一项任务并单击该按钮应将任务从待办事项列表移动到正在执行的列表中。

我见过的每个 SwiftUI 列表选择示例都使用导航链接。选择一个列表项会将您带到另一个视图。但我不想在选择列表项时导航到另一个视图。我想要选定的任务,以便在单击按钮时更改其状态并将其移动到正确的列表中。

这是我的一份清单的代码。

struct TodoList: View {
    // The board has an array of tasks.
    @Binding var board: KanbanBoard
    @State private var selection: Task? = nil
    @State private var showAddSheet = false
    
    var body: some View {
        VStack {
            Text("Todo")
                .font(.title)
            List(todoTasks, selection: $selection) { task in
                Text(task.title)
            }
            HStack {
                Button(action: { showAddSheet = true }, label: {
                    Label("Add", systemImage: "plus.square")
                })
                Spacer()
                Button(action: { selection?.status = .doing}, label: {
                    Label("Start Doing", systemImage: "play.circle")
                })
            }
            
        }
        .sheet(isPresented: $showAddSheet) {
            AddTaskView(board: $board)
        }
    }
    
    var todoTasks: [Task] {
       // Task conforms to Identifiable. 
       // A task has a status that is an enum: todo, doing, or done.
        return board.tasks.filter { $0.status == .todo}
    }
}

当我点击一个列表项时,它没有被选中。

如何在不使用导航链接的情况下从列表中获取所选项目?

解决方法

Tamas Sengel 的回答让我找到了解决方法。为每个列表项提供一个开始执行按钮,这样我就不必跟踪选择。

List(todoTasks, id: \.self) { task in
    HStack {
        Text(task.title)
        Button {
            task.status = .doing
        } label: {
            Text("Start Doing")
        }
    }
                
}

解决方法有助于我的具体情况。但我将保持这个问题的开放性,希望得到一个答案,为想要获取所选列表项的人提供更好的选择,而不是使用按钮。

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    在列表和操作中使用按钮,将@State 变量设置为当前列表项。

    @State var currentTask: Task?
    
    List(todoTasks, id: \.self) { task in
        Button {
            currentTask = task
        } label: {
            Text(task.title)
        }
    }
    

    【讨论】:

      【解决方案2】:

      使用.environment(\.editMode, .constant(.active)) 开启选择功能。

      import SwiftUI
      
      struct ContentView: View {
          struct Ocean: Identifiable, Hashable {
              let name: String
              let id = UUID()
          }
          private var oceans = [
              Ocean(name: "Pacific"),
              Ocean(name: "Atlantic"),
              Ocean(name: "Indian"),
              Ocean(name: "Southern"),
              Ocean(name: "Arctic")
          ]
          @State private var multiSelection = Set<UUID>()
          
          var body: some View {
              NavigationView {
                  List(oceans, selection: $multiSelection) {
                      Text($0.name)
                  }
                  .navigationTitle("Oceans")
                  .environment(\.editMode, .constant(.active))
                  .onTapGesture {
                      // This is a walk-around: try how it works without `asyncAfter()`
                      DispatchQueue.main.asyncAfter(deadline: .now() + 0.05, execute: {
                          print(multiSelection)
                      })
                  }
              }
              Text("\(multiSelection.count) selections")
          }
      }
      
      struct ContentView_Previews: PreviewProvider {
          static var previews: some View {
              ContentView()
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 2011-01-16
        • 2022-06-23
        相关资源
        最近更新 更多