如何在 SwiftUI 中分配可选的绑定参数?

How to assign an optional Binding parameter in SwiftUI?

我正在尝试使用一些可选的 Views 构建自定义 NavBar,例如搜索栏(但仅当视图需要显示它时)。

基本上,我需要通过 @Binding 在视图中传递一些 @State 属性。但我还需要它们作为 Optional 参数。

这是一个例子:

struct NavBar: View {
    
    var isSearchable: Bool?
    
    @Binding var searchTxt: String
    @Binding var searchIsOn: Bool
    
    var navBarTitle: String
    var navBarAction: (() -> Void)?
    var navBarImage: String?
    
    init(navBarTitle: String, navBarAction: (() -> Void)? = nil, navBarImage: String? = nil, isSearchable: Bool? = false, searchTxt: (Binding<String>)?, searchIsOn : (Binding<Bool>)?) {
        self.navBarTitle = navBarTitle
        if(navBarAction != nil) {
            self.navBarAction = navBarAction!
        }
        if(navBarImage != nil) {
            self.navBarImage = navBarImage!
        }
        self.isSearchable = isSearchable
        
        self._searchTxt = (searchTxt != nil) ? (searchTxt!).binding : nil
        self._searchIsOn = (searchIsOn != nil) ? (searchIsOn!).binding : nil
        
        assert((navBarAction != nil) ? navBarImage != nil : true)
        assert((isSearchable! == true) ? (searchTxt!.value.count > 0) : true)
    }
// var body ....

}

我说的属性是 searchIsOnsearchTxt。 但是执行赋值 self._searchTxt = searchTxtself._searchIsOn = searchIsOn 会引发编译错误:

Cannot assign value of type 'Binding?' to type 'Binding'

你知道我该如何解决这个问题吗?

或者是否有更好的方法来完成我想做的事情?

我有一个 UIViewControllerRepresentable 以便使用 UIImagePickerController。如果你曾经使用过这个图像选择器,你就会知道你需要将返回的图像作为一个可选的。所以在我的 ContentView 中我声明:

@State var uiImage: UIImage?

...

if uiImage != nil {
    Image(uiImage: $uiImage)
} else {
    Rectangle()
}

在我的 ImagePicker 中(这是我的 SwiftUI 视图)我有:

@Binding var uiImage: UIImage?

很有魅力。

if 语句几乎是 psuedo-code,因为我实际上使用的是 MTKViewCIImage,但你明白了 - 你使用就像你在其他任何地方一样是可选的。)

@Binding var searchTxt: String?

init(searchTxt: Binding<String?>?) {
    self._searchTxt = searchTxt ?? Binding.constant(nil)
}

更新:我更喜欢这个。 TextField("", text: $text ?? "default value")

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

您想要的是字符串的可选绑定,而不是可选字符串的绑定。我不认为你可以通过使用 @Binding 注释来实现。

但是,您不需要使用注释。您可以将变量声明为绑定:

你的

@Binding var searchTxt: String?

然后转向这个

var searchTxt: Binding<String?>

但是这种语法可以让你放置 ?哪里都行。所以如果你把它移到最后,在 Binding 的结束标记之后,你就有了你想要的。

var searchTxt: Binding<String>?

如果你想访问 Binding 中的字符串,你必须使用 wrappedValue 属性。

Text(searchTxt!.wrappedValue)

下面是使用可选绑定以及如何访问绑定和切换以显示某些视图的示例:

struct NavBar: View {
    @Binding var showUser: Bool
    var showOptional: Binding<Bool>?
    
    var body: some View {
    
    VStack {
     Button(action: { showUser.toggle() },
            label: { Text("NOT OPTIONAL") })
    
     Button(action: { showSelectBuddy?.wrappedValue.toggle()) },
            label: { Text("NOT OPTIONAL") })
    
    }
    }
    }

    struct UseNavbar: View {
    
    @State var showoptional = false
    @State var show = false 
    
    var body: some View {
    Text("Optional")
    .navigationBarItems(leading:
    NavBar(showUser: show), trailing: NavBar(showUser: show, showOptional: showoptional))
    }
    }