SwiftUI:创建自定义绑定

作者: 韦弦Zhy | 来源:发表于2020-06-02 19:57 被阅读0次

    \color{red}{\Large \mathbf{Hacking \quad with \quad iOS: SwiftUI \quad Edition}}

    {\Large \mathbf{Instafilter}}

    由于SwiftUI将绑定更新发送到属性包装器的方式,分配与属性包装器一起使用的属性观察器将无法正常工作,这意味着即使模糊半径发生变化,此类代码也不会打印任何内容:

    struct ContentView: View {
        @State private var blurAmount: CGFloat = 0 {
            didSet {
                print("New value is \(blurAmount)")
            }
        }
    
        var body: some View {
            VStack {
                Text("Hello, World!")
                    .blur(radius: blurAmount)
    
                Slider(value: $blurAmount, in: 0...20)
            }
        }
    }
    

    要解决此问题,我们需要创建一个自定义绑定——我们需要直接使用Binding结构体,该结构体在读取或写入值时允许我们提供我们自己的代码来运行。

    在我们的代码中,我们希望Binding在读取时返回blurAmount的值,但是在写入时,我们想要更改blurAmount的值并打印该新值,以便我们可以看到它已更改。不管我们是在读取还是在写入,我们都在谈论读取了blurAmount属性的内容,而Swift不允许我们创建读取其他属性的属性,因为我们尝试读取的属性可能尚未创建。

    因此,将所有这些放在一起,我们需要创建一个自定义的Binding结构体,该结构充当blurAmount的传递对象,但是当我们设置该值时,我们还希望打印一条消息。另外,我们也不得将其存储为视图的属性,因为不允许从另一个属性读取一个属性。

    所以,我们需要将此代码放入视图的body属性中,如下所示:

    struct ContentView: View {
        @State private var blurAmount: CGFloat = 0
    
        var body: some View {
            let blur = Binding<CGFloat>(
                get: {
                    self.blurAmount
                },
                set: {
                    self.blurAmount = $0
                    print("New value is \(self.blurAmount)")
                }
            )
    
            return VStack {
                Text("Hello, World!")
                    .blur(radius: blurAmount)
    
                Slider(value: blur, in: 0...20)
            }
        }
    }
    

    在进入绑定本身之前,请注意其他内容如何保持不变:我们仍然使用@State private var声明blurAmount属性,并且仍然使用.blur(radius: blurAmount)作为文本视图的修饰符。

    更改的一个地方是我们在滑块中声明绑定的方式:我们不在使用$blurAmount,而是直接使用blur。这是因为使用美元符号可以使我们从某个状态属性获得双向绑定,但是现在我们已经直接创建了绑定,因此不再需要它。

    好的,现在让我们来看一下绑定本身。您应该可以从我们的使用方式中看出来,Binding的基本初始化器如下所示:

    init(get: @escaping () -> Value, set: @escaping (Value) -> Void)
    

    您可以通过按 Cmd + Shift + O 并在已生成的SwiftUI界面中查找“Binding”来找到它。详细地讲,它告诉我们初始化程序采用两个闭包:一个不带参数并返回值的getter,和一个带值但不返回任何值的setter。绑定使用泛型,因此Value实际上是我们存储在内部的所有内容的占位符——对于我们的模糊绑定而言是CGFloatgetset闭包都标记为@escaping,这意味着Binding结构体存储它们供以后使用。

    这意味着您可以在这些闭包内做任何您想做的事情:可以调用方法,运行算法以找出要使用的正确值,甚至只是使用随机值——没关系,只要您从get返回值。因此,如果要确保每次更改值时都更新UserDefaults,则Bindingset闭包是完美的。

    译自 Creating custom bindings in SwiftUI

    相关文章

      网友评论

        本文标题:SwiftUI:创建自定义绑定

        本文链接:https://www.haomeiwen.com/subject/mjcfzhtx.html