列表选择为 Set<String> - 如何使用?
Posted
技术标签:
【中文标题】列表选择为 Set<String> - 如何使用?【英文标题】:List selection as Set<String> - how to use? 【发布时间】:2019-12-27 15:19:32 【问题描述】:我在玩 SwiftUI,但显然没有得到它。
基本示例,仅显示所选名称。
struct ContentView: View
let names = ["Joe", "Jim", "Paul"]
@State var selectedName = Set<String>()
var body: some View
VStack
List(names, id: \.self, selection: $selectedName) name in
Text(name)
if !selectedName.isEmpty
Text(selectedName.first!) // <-- this line
我想要的是一个可以更改名称的文本字段。尝试了很多方法,但每次都得到另一个错误。
TextField("Name", text: $selectedName)
给出此错误:无法将“Binding
>”类型的值转换为预期的参数类型“Binding ”
TextField("Name", text: $selectedName.first!)
不能强制解开非可选类型'Binding Bool) throws -> String?>'的值
我该怎么做?
【问题讨论】:
【参考方案1】:您可以自行绑定:
TextField("Name", text: Binding<String>(get: self.selectedName.first!, set: _ in) )
【讨论】:
非常感谢!我到处寻找所有解决方案,您的解决方案是最好的!【参考方案2】:显然你不能将Binding<Set<String>>
传递给Binding<String>
。这里为您提供了使用 TextField 更改 selectedName 变量的想法或解决方案:
我添加了一个新变量 Binding<String>
。然后我在 TextField 的 onCommit
闭包中更改 selectedName。
struct ContentView: View
let names = ["Joe", "Jim", "Paul"]
@State var selectedName = Set<String>()
@State var textFieldName = ""
var body: some View
VStack
List(names, id: \.self, selection: $selectedName) name in
Text(name)
if !selectedName.isEmpty
Text(selectedName.first!)
Text(textFieldName)
TextField("Name", text: $textFieldName, onEditingChanged: (Bool) in
//onEditing
)
//onCommit
self.selectedName.insert(self.textFieldName)
【讨论】:
【参考方案3】:好的,如果我需要在一个屏幕中编辑 names
的某些值并列出和编辑字段并使它们全部同步且不会相互混淆,这是我的替代方法。
这是完整的可测试模块(在 Xcode 11.2/ios 13.2 上测试)。当我为 iOS 测试它时,有 API 要求将 List
放入 EditMode 以处理选择,因此包括在内。
struct TestChangeSelectedItem: View
@State var names = ["Joe", "Jim", "Paul"] // made modifiable
@State var selectedName: String? = nil // only one can be edited, so single selection
@State var editMode: EditMode = .active // Tested for iOS, so it is needed
var body: some View
VStack
List(selection: $selectedName)
ForEach(names, id: \.self) name in
Text(name)
.environment(\.editMode, $editMode) // Tested for iOS, so it is needed
if selectedName != nil
Divider()
Text(selectedName!) // Left to see updates for selection
editor(for: selectedName!) // Separated to make more clear
private func editor(for selection: String) -> some View
let index = names.firstIndex(of: selection)!
var editedValue = selection // local to avoid cycling in refresh
return HStack
Text("New name:")
TextField("Name", text: Binding<String>(get: editedValue , set: editedValue = $0), onCommit:
self.names[index] = editedValue
self.selectedName = editedValue
)
struct TestChangeSelectedItem_Previews: PreviewProvider
static var previews: some View
TestChangeSelectedItem()
【讨论】:
以上是关于列表选择为 Set<String> - 如何使用?的主要内容,如果未能解决你的问题,请参考以下文章
C# 从 List<T> 中选择存在于另一个列表中的所有元素
Java 将 Map<String,Set<String>> 转换为 Map<String,Set<Object1>> [关闭]