为啥我不能强制解开我的 $string 以用作 TextField 值?

Posted

技术标签:

【中文标题】为啥我不能强制解开我的 $string 以用作 TextField 值?【英文标题】: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 严重依赖非可选项,您应该首先寻找一种避免可选项的设计。 【参考方案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 所做的更好;更新你的答案,我会删除我的,因为你有更完整的信息。 现在,这有多酷。不完全确定我理解映射发生了什么,但是谢谢,伙计们,这完全为我整理好了!

以上是关于为啥我不能强制解开我的 $string 以用作 TextField 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用警卫同时解开 Swift 可选和强制类型转换?

为啥我们不能使用 CloudFormation 中的参数将 AllowedValues 用作字符串?

为啥 $ 符号不能用作标识符的一部分? [复制]

无法强制解开非可选类型“UIImage”的值

为啥 ref 结构不能用作类型参数?

为啥不能在 Django ManyToMany 字段上强制执行唯一性?