将选择列为"设置"<String>-如何使用?



我正在玩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)

给出此错误:无法将类型"绑定<集><字符串>>"的值转换为预期的参数类型"绑定<字符串>

TextField("Name", text: $selectedName.first!)

无法强制解开非可选类型"绑定<(字符串(抛出 -> 布尔(抛出 -> 字符串?"的值>

我该怎么做?

您可以自己进行绑定:

TextField("Name", text: Binding<String>(get: {self.selectedName.first!}, set: { _ in}) )

显然你不能把Binding<Set<String>>传递给Binding<String>.这里为您提供了一个使用文本字段更改 selectedName 变量的想法或解决方案:

我添加了一个新变量,它是Binding<String>.然后,我在文本字段的onCommit闭包中更改所选名称。

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)
}
}
}
}

好的,如果我需要编辑names在一个屏幕中的某些值,列出和编辑字段并使它们全部同步而不会相互混淆,这是我的替代方案。

这是完整的可测试模块(在Xcode 11.2/iOS 13.2上测试(。当我为 iOS 测试它时,List进入编辑模式以处理选择有 API 要求,所以这包括。

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()
}
}

最新更新