专栏首页韦弦的偶尔分享SwiftUI:创建自定义绑定

SwiftUI:创建自定义绑定

由于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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用Vapor 3 创建项目build/xocde 报错

    以前跟着网上的教程玩过Vapor2,但基本都忘光了,今天下班了有照着官方文档来一波。。。但是出错了。。。

    韦弦zhy
  • UIViewController初始化没有 init 导致的 Bug

    话说 *** Assertion failure in UITraitCollection * _Nonnull _UIGetCurrentFallbackT...

    韦弦zhy
  • Swift 罗马数字转整数 - LeetCode

    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II ...

    韦弦zhy
  • app框架整体设计

    程序员不务正业
  • 自定义网页QQ登录按钮

    QQ互联为网页的 QQ 登录提供了统一接口,但是其样式比较固定,风格陈旧,没有提供完全自定义的接口。在此介绍一种自定义按钮风格的方法。

    tonglei0429
  • VR开发-VRTK(3.1.0)插件使用教程更新

    最近插件更新了,很多以前的组件功能被修改了。表示蛋疼。。。 再说一次不要使用最新的Unity版本,尤其5.6,手柄渲染不出来 #Unity 5.5.1,目前...

    雷潮
  • 算法效率分析基础

    版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.ne...

    zy010101
  • 高效程序员的MacBook工作环境配置

    高效程序员的MacBook工作环境配置 本文记录整个配置过程,供新入手 MacBook 和觉得 MacBook 比较难用的同学参考。 1. 硬件提升 笔记本电脑...

    用户1289394
  • 一篇文章让你的 MacBook 进入超神状态

    工欲善其事,必先利其器,工具永远都是用来解决问题的,没必要为了工具而工具,一切工具都是为了能快速准确的完成工作和学习任务而服务。

    小小詹同学
  • 一篇文章带你登顶 MacBook 高效工作环境配置

    笔记本电脑的特点是携带方便,缺点是屏幕太小,因此你首先需要再申请领用一个外接显示器,多一个屏幕会大大减少你切换应用程序的次数,显著提升你的工作效率,别忘了同时申...

    崔庆才

扫码关注云+社区

领取腾讯云代金券