将可选绑定转换为非可选绑定

use*_*ser 6 swift swiftui

我想要使​​用一个函数来扩展 Binding 扩展,我们可以将可选 Binding 转换为非可选 Binding 并将其用作普通 Binding。我几乎可以完成它,但是 xCode 通过一个我无法处理的错误,我认为我所做的一切都是正确的。

extension Binding {
    
    mutating func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
        
        let safeValue: T
        
        if let unwrappedValue: T = self.wrappedValue { safeValue = unwrappedValue }
        else { safeValue = defaultValue }

        return Binding.init(get: { () -> T in return safeValue },
                            set: { (newValue) in self.wrappedValue = newValue })
 
        
    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

Cannot convert return expression of type 'Binding<Optional<T>>' to return type 'Binding<T>'
Run Code Online (Sandbox Code Playgroud)

按照我的方式更新了代码:

extension Binding {
    
     func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
        
        let safeValue: T
        
        if let unwrappedValue: T = self.wrappedValue { safeValue = unwrappedValue }
        else { safeValue = defaultValue }

        return SwiftUI.Binding.init(get: { () -> T in return safeValue },
                                    set: { (newValue) in self.wrappedValue = newValue })
 
        
    }
}
Run Code Online (Sandbox Code Playgroud)

jn_*_*pdx 8

Binding已经有一个关联的类型Value,因此通过尝试使用T,您将在已经存在的 之上放置一个新的泛型Value

但是,您最终仍会使用,T因为您希望限制Value它是可选的场景:

extension Binding {
    func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
        .init {
            self.wrappedValue ?? defaultValue
        } set: { newValue in
            self.wrappedValue = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如评论中所指出的,如果Binding.init使用 just ,Xcode 编译器会遇到困难(请注意,我使用 just .init)。这可以通过显式使用来解决Binding<T>.init

extension Binding {
    func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
        Binding<T>.init {
            self.wrappedValue ?? defaultValue
        } set: { newValue in
            self.wrappedValue = newValue
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)