首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

SwiftUI变量: willSet,didSet

SwiftUI 变量:willSetdidSet

基础概念

在 SwiftUI 中,willSetdidSet 是属性观察器(Property Observers),用于在属性值即将改变或已经改变时执行特定的代码块。这两个观察器可以帮助开发者监控和管理属性值的变化。

  • willSet:在属性值即将被设置之前调用。
  • didSet:在属性值已经被设置之后调用。

优势

  1. 实时监控:可以实时监控属性值的变化,便于执行一些副作用操作。
  2. 数据验证:在属性值设置前后进行验证和处理,确保数据的有效性。
  3. 简化逻辑:通过观察器可以集中处理属性值变化相关的逻辑,使代码更加简洁和易于维护。

类型

  • 局部变量:不能在局部变量上使用 willSetdidSet
  • 实例属性:可以在类的实例属性上使用。
  • 计算属性:计算属性不能使用 willSetdidSet

应用场景

  1. 数据验证:在设置属性值之前进行验证,确保数据的合法性。
  2. 副作用处理:在属性值变化时执行一些副作用操作,如更新UI、记录日志等。
  3. 依赖更新:当属性值变化时,通知其他依赖该属性的组件进行更新。

示例代码

代码语言:txt
复制
class User {
    var name: String = "" {
        willSet(newName) {
            print("即将设置新的名字: \(newName)")
        }
        didSet(oldName) {
            if name != oldName {
                print("名字已从 \(oldName) 改为 \(name)")
            }
        }
    }
}

let user = User()
user.name = "Alice" // 输出: 即将设置新的名字: Alice
                   //       名字已从  改为 Alice

user.name = "Bob"   // 输出: 即将设置新的名字: Bob
                   //       名字已从 Alice 改为 Bob

遇到的问题及解决方法

问题:在 didSet 中修改属性值会导致无限循环。

原因:如果在 didSet 中直接修改同一个属性,会导致该属性再次触发 didSet,从而形成无限循环。

解决方法:避免在 didSet 中直接修改同一个属性。如果需要修改,可以考虑使用一个临时变量来处理逻辑。

代码语言:txt
复制
class User {
    var name: String = "" {
        didSet(oldName) {
            if name != oldName {
                let newName = processName(name)
                self.name = newName // 这里不会导致无限循环,因为是通过临时变量处理的
            }
        }
    }

    private func processName(_ name: String) -> String {
        // 进行一些处理,例如转换为大写
        return name.uppercased()
    }
}

let user = User()
user.name = "Alice" // 输出: 名字已从  改为 ALICE

通过这种方式,可以有效地避免无限循环的问题,同时确保属性值的变化得到正确的处理。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

swift底层探索 02 - 属性swift底层探索 02 - 属性

Swift的属性分为: 存储属性 计算属性 属性观察者(didSet、willSet) 延迟存储属性 类型属性 1. 存储属性: 可以保存各类信息的属性,需要占用内存空间。 ?...属性观察者(willSet、didSet) 作用可以简单的理解为oc中的KVO,区别是使用更加简单,但也有自己的一些规则. ? willSet:新值存储之前调用....内建变量newValue didSet:新值存储之后调用. 内建变量OldValue ?...在你使用属性观察者(willSet、didSet)之后,在编译阶段会在set方法中增加调用这两个方法的代码。当然这些都是编译器完成的,不需要我们再去进行额外的操作。 在使用过程中有几个问题: 1....子类和父类同时存在didset、willset时,其调用顺序 ? 调用顺序:子类的willSet->父类的wilSet->父类的didSet->子类的didset 4.

95840
  • swift 属性(存储属性、计算属性、懒加载属性、类型属性)

    存储属性 存储属性:用于存储一个常量或变量 结构体实例赋值给常量,该实例属性不能被修改(因为结构体属于值类型,当值类型的实例被声明为常量的时候,它的所有属性也就成了常量) struct Teacher...teacher.name = "good teacher" //报错 类实例赋值给常量,可以修改该实例变量属性(类属于引用类型) class Student: NSObject { var...在属性声明前使用 lazy 来表示延迟存储属性 注意:必须将延迟存储属性声明成变量,因为属性的初始值可能在实例构造完成之后才会得到。...在新的值被设置之前调用(willSet 会将新属性值作为常量参数传入,默认名称 newValue 表示) didSet 在新的值被设置之后调用(didSet会将旧属性值作为参数传入,默认参数名 oldValue...和 didSet 观察器会被调用,随后才会调用子类的观察器。

    29210

    Swift 属性

    可以为属性添加如下的一个或全部观察器: willSet 在新的值被设置之前调用 didSet 在新的值被设置之后立即调用 willSet 观察器会将新的属性值作为常量参数传入,在 willSet 的实现代码中可以为这个参数指定一个名称...注意 父类的属性在子类的构造器中被赋值时,它在父类中的 willSet 和 didSet 观察器会被调用,随后才会调用子类的观察器。...下面是一个 willSet 和 didSet 实际运用的例子,其中定义了一个名为 StepCounter 的类,用来统计一个人步行时的总步数。...当 totalSteps 被设置新值的时候,它的 willSet 和 didSet 观察器都会被调用,即使新值和当前值完全相同时也会被调用。...didSet 没有为旧值提供自定义名称,所以默认值 oldValue 表示旧值的参数名。 注意 如果将属性通过 in-out 方式传入函数,willSet 和 didSet 也会调用。

    85110

    Swift讲解专题十一——属性 原

    二、存储属性         存储属性使用变量或者常量来存储一个值,在声明存储属性时,可以为其设置一个默认值,也可以在构造示例是进行值的设置,属性可以通过点语法来访问,结构体的存储属性示例代码如下: struct...还有一点需要注意,如果在创建结构体的实例时,使用的是let进行创建,则即便结构体中的属性是变量也不可进行修改。这和类有很大区别。        ...属性监听器有willSet和didSet两种,willSet在属性值将要变化时执行,didSet在属性值已经变化时执行,并且其中会传入变化前后的值。...,新的值是:",newValue) } didSet{ print("已经进行值得更新设置,旧的值是:",oldValue) }...var y:Double{ willSet(new){ print("将要进行值的更新设置,新的值是:",new) }

    48430

    Swift基础 属性

    您可以选择在属性上定义以下一个或多个观察者: willSet在存储值之前调用。 didSet在存储新值后立即调用。...注意 在调用超类初始化器后,当在子类初始化器中设置属性时,调用超类属性的willSet和didSet观察器。在调用超类初始化器之前,当类设置自己的属性时,不会调用它们。...以下是willSet和didSet执行的实例。下面的示例定义了一个名为StepCounter的新类,该类跟踪一个人在行走时采取的总步数。...This is a stored property with willSet and didSet observers....注意 如果您将具有观察者作为进出参数的函数的属性传递,则始终调用将willSet和didSet观察者。这是因为输入输出参数的复制内存模型:该值总是写回函数末尾的属性。

    23500

    18.Swift学习之属性与方法

    类的属性介绍 Swift中属性有多种 存储属性:存储实例的常量和变量 计算属性:通过某种方式计算出来的属性 类属性:与整个类自身相关的属性 存储属性 存储属性是最简单的属性,它作为类实例的一部分,用于存储常量和变量...(对于计算属性,- 我们不需要定义属性观察者,因为我们可以在计算属性的setter中直接观察并响应这种值的变化) 我们通过设置以下观察方法来定义观察者 willSet:在属性值被存储之前设置。...该参数名默认为newValue,我们可以自己定义该参数名 didSet:在新属性值被存储后立即调用。...与willSet相同,此时传入的是属性的旧值,默认参数名为oldValue willSet与didSet只有在属性第一次被设置时才会调用,在初始化时,不会去调用这些监听方法 监听的方式如下: 监听age...用于存储新值 print(name) print(new) } // 可以给oldValue自定义名称 didSet

    57030

    Swift学习:属性

    添加属性观察器方式如下: willSet方法: 在新的值被设置之前调用,拥有一个默认参数newValue(代表新的属性值); didSet方法: 在新的值被设置之后立刻调用,拥有一个默认参数oldValue...和didSet括号中的值可以省略,直接使用系统自带的newVlaue和oldValue var currentDianYa = 0 { //可以使用系统默认的属性newValue...)") } //当调用此方法时,已经设置了值的时候, didSet(oldCurentDianYa){ if(currentDianYa...和didSet并不会在初始化时被调用 三、类型属性 实例属性属于一个特定类型的实例,因此实例之间的属性相互独立。...全局变量:在函数、方法、闭包或者任意类型之外定义的变量 局部变量:在函数、方法或者闭包内部定义的变量 全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地方在于:全局的常量或变量不需要标记lazy

    63320

    iOS 面试策略之语言工具-Swift

    他们遵循的基本原则是:高级别的变量不允许被定义为低级别变量的成员变量。比如一个 private 的 class 中不能含有 public 的 String。...关键词:#willSet #didSet 属性观察是指在当前类型内对特定属性进行监视,并作出响应的行为。它是 Swift 的特性,有两种,为 willSet 和 didSet。...举个例子: var title: String { willSet { print("将标题从\(title)设置到\(newValue)") } didSet { print...当 title 发生改变前,willSet 对应的作用域将被执行,新的值是 newValue;当 title 发生改变之后,didSet 对应的作用域将被执行,原来的值为 oldValue。...加分回答: 初始化方法对属性的设定,以及在 willSet 和 didSet 中对属性的再次设定都不会触发属性观察的调用。 Swift 面试实战题 9.

    1.4K10

    窥探Swift之别具一格的Struct和Class

    Struct (结构体)     结构体,说白了就是一组变量,这些变量有统一的命名。在Swift中,我们不仅可以在Struct中声明变量并为变量设置默认值,而且可以在Struct中添加相应的函数。...2.结构体类型变量的声明以及结构体函数的使用     接下来我们就利用上述“MyPoint”结构体类型来创建一个结构体类型变量。...2.对象的赋值与比较     在Swift中也是允许把一个类的变量的值通过赋值运算符(=)来赋值给另一个变量的。不过有一点要搞明白,如果类变量a的值赋值被类变量b,那么变量a和b就指向同一块内存区域。...说白了,属性观测器就是来观察属性的赋值情况的,属性观测器包括willSet()和didSet , willSet在属性将要被赋值的时候被调用, didSet是在属性被赋值后调用,关于这两个属性观察函数,...由下方实例可知,在willSet调用时,property属性的值还为默认值,但是在didSet执行时,property的值已经成为被赋予的值了。 ?     6.

    1K70
    领券