我熟悉SwiftUI中绑定到可选属性,但是如何绑定到可选值的property呢?在下面的例子中,cat是可选的,但cat.name不是可选的.我该如何使用cat.name

import SwiftUI

class Cat {
    var name: String = ""
    
    init(name: String) {
        self.name = name
    }
}

class CatManager: ObservableObject {
    var cat: Cat? = Cat(name: "Jiji")
}

struct TestOptional: View {
    
    @ObservedObject var catManager: CatManager
    
    var body: some View {
        
        // Value of optional type 'Cat?' must be unwrapped to refer to member 'name' of wrapped base type 'Cat'
        TextField("Cat's name", text: $catManager.cat.name)
        
        // Value of optional type 'Binding<String?>?' must be unwrapped to a value of type 'Binding<String?>'
        TextField("Cat's name", text: $catManager.cat?.name ?? "")
    }
}

func ??<T>(lhs: Binding<Optional<T>>, rhs: T) -> Binding<T> {
    Binding(
        get: { lhs.wrappedValue ?? rhs },
        set: { lhs.wrappedValue = $0 }
    )
}

在每个文本字段上方的注释中显示错误消息.

推荐答案

首先,考虑一下当cat为零时文本字段会做什么.没有cat,因此没有name可供文本字段绑定.如果希望文本字段使用文本字段的文本创建新的Cat,则可以将此类属性添加到CatManager,并改为绑定到此属性:

var catName: String {
    get { cat?.name ?? "" }
    set {
        if cat == nil {
            cat = Cat(name: newValue)
        } else {
            cat?.name = newValue
        }
    }
}

当然,这并不总是可能的.Cat.init可能需要其他参数.在这种情况下,文本字段什么也做不了,是吗?

您可以使用Binding个初始值设定项之一将Binding<Cat?>转换为Binding<Cat>?.当此绑定为空时,您将无法执行任何操作,因此您可以只显示其他内容,或禁用文本字段.

if let binding = Binding($catManager.cat) {
    TextField("Cat's name", text: binding.name)
} else {
    Text("There is no cat!")
}

TextField("Cat's name", text: Binding($catManager.cat)?.name ?? .constant(""))
    .disabled(catManager.cat == nil)

其他注意事项:

  • CatManager.cat应为@Published,以便SwiftUI视图可以观察到对其的更改
  • Cat should be a struct. If you really need it to be a class f或 some reason, mark both Cat and CatManager as @Observable, and use @Bindable to get a Binding.

Swift相关问答推荐

JSON如何解码空对象

如何避免使用DispatchSemaphores时线程爆炸?

为什么我的引用类型对象在初始化后有3个强引用?

如何使用swift宏生成一个带有关联值的枚举?

如何返回JSON数据?

如何让ScrollView缩小到合适的大小,并在没有黑客攻击的情况下占用最小空间

如何在SwiftUI 4+(iOS 16+)中使用新的NavigationStack进行导航

如何避免切换视图递归onChange调用SwiftUI

如何在一个视图控制器中创建具有相同行为的多个集合视图?

如何删除 macOS 中的所有命令?

iOS16 Bug 键盘在表单解雇 SwiftUI 时打破布局

使用泛型的 Swift 枚举值

Swift 有没有办法在不使用 switch 语句的情况下获取关联值?

如何 for each 用户制作一个单独的按钮,以便在按下它时切换 isFollowingUser Bool 并更改为关注?

Swift初始化具有可变ID的重复值数组

在 Select 器上显示alert Select SwiftUI

Xcode 13.3 将函数调用更改为属性访问

如何快速制作虚线?

即使设置为从不也可以访问 iOS11 照片库

使用 phimagemanager 将图像保存到自定义相册?