Swift 中的属性观察器是什么?如何使用 willSet 和 didSet?
Swift 中的属性观察器用于监控和响应属性值的变化。当属性值被设置时,属性观察器会被触发,允许你在值改变前后执行自定义代码。
属性观察器的类型:
-
willSet:
- 在新值存储之前调用
- 可以访问新值(通过默认参数名 newValue)
- 可以在设置新值之前执行验证或准备工作
- 示例:
swift
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } } }
-
didSet:
- 在新值存储之后调用
- 可以访问旧值(通过默认参数名 oldValue)
- 可以在值改变后执行更新或通知操作
- 示例:
swift
class StepCounter { var totalSteps: Int = 0 { didSet { print("Added \(totalSteps - oldValue) steps") } } }
完整示例:
swiftclass TemperatureMonitor { var temperature: Double { willSet { print("Temperature will change from \(temperature) to \(newValue)") if newValue > 100 { print("Warning: High temperature!") } } didSet { print("Temperature changed from \(oldValue) to \(temperature)") if temperature != oldValue { notifyTemperatureChange() } } } func notifyTemperatureChange() { print("Notifying temperature change...") } } let monitor = TemperatureMonitor() monitor.temperature = 25 monitor.temperature = 105
属性观察器的使用场景:
-
数据验证:
swiftclass Person { var age: Int { didSet { if age < 0 { age = 0 } if age > 150 { age = 150 } } } } -
UI 更新:
swiftclass ViewModel { var isLoading: Bool = false { didSet { updateLoadingIndicator() } } func updateLoadingIndicator() { // 更新 UI 指示器 } } -
缓存失效:
swiftclass DataCache { var data: [String: Any] = [:] { didSet { invalidateCache() } } func invalidateCache() { // 清除缓存 } } -
日志记录:
swiftclass Logger { var logLevel: LogLevel = .info { didSet { print("Log level changed from \(oldValue) to \(logLevel)") } } }
注意事项:
- 属性观察器不能用于延迟属性(lazy)
- 属性观察器不能用于常量属性(let)
- 在初始化器中设置属性值不会触发属性观察器
- 在 willSet 中修改属性值不会再次触发 willSet
- 在 didSet 中修改属性值会再次触发属性观察器
- 如果属性有默认值,初始化时不会触发属性观察器
最佳实践:
- 使用 willSet 进行值验证和准备
- 使用 didSet 执行副作用和更新
- 避免在属性观察器中执行耗时操作
- 注意避免无限循环(在 didSet 中修改属性)
- 使用有意义的参数名提高代码可读性