【问题标题】:Why can't I force unwrap my $string to use as a TextField value?为什么我不能强制解开我的 $string 以用作 TextField 值?
【发布时间】:2021-05-03 11:32:12
【问题描述】:

这给了我以下错误: 无法强制解开非可选类型 'Binding

的值

我不明白为什么我不能强制解开绑定?

struct Person {
    var name: String
}

struct ContentView: View {

    @State private var person: Person? = Person(name: "Peter")
    
    var body: some View {
        if person != nil {
            TextField("", text: $person!.name)
        }
    }
}

【问题讨论】:

  • 题外话,但您确定要将像 Person 这样的模型对象作为状态变量吗?
  • 为什么person 是可选的?
  • @JoakimDanielson 你是对的,我不会。我从我的代码中提取了这个以简化示例。
  • @vadian。提取代码以简化示例。但是假设您有一个可供选择的人员列表,一个选项是根本不选择一个人。在这种情况下, Person 将为零,所以我需要计算
  • 我不明白。如果您有一个列表,则该对象是一个数组,而 none selected 是一个空数组。如果视图是列表中的行视图,则如果未选择该行,则不会显示该视图。我想说的是,与 Swift 语言不同,SwiftUI 严重依赖非可选项,您应该首先寻找一种避免可选项的设计。

标签: swiftui textfield


【解决方案1】:

当您在视图中声明State 变量时,您将通过在变量名称中添加前导$ 来获得Binding 值。 因此,在您的代码中,您将拥有一个绑定到可选 Person 类型的 $person$personBinding<Person?>

要将值传递给TextField,您需要Binding<String>。您不能强制解开 $person,因为它不是可选值。这是一个可选类型的Binding。要访问Person 结构中的name 字段,您需要一个Binding<Person>。 幸运的是,有一种方法可以得到你想要的。 通过使用this initializer,您将拥有Binding<Person>?。请注意,现在你有一个可选的Binding,而不是一个可选的Binding。 您应该可以像这样使用这个新绑定:

// Binding($person) returns Binding<Person>? 
TextField("", text: Binding($person)!.name)

更新: 正如@Jessy 在 cmets 中提到的,我们可以使用map 将返回的Binding 转换为TextField,而不是强制解包可选绑定。

var body: some View {
   Binding($person).map {
     TextField("", text: $0.name)
   }
}

【讨论】:

  • 该初始化程序是解决方案的一个很好的部分,但 ! 不是一个好方法。 if let 或我对 map 所做的更好;更新你的答案,我会删除我的,因为你有更完整的信息。
  • 现在,这有多酷。不完全确定我理解映射发生了什么,但是谢谢,伙计们,这完全为我整理好了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
相关资源
最近更新 更多