onChange 是 SwiftUI 中的一个视图修饰符,用于监听某个状态值的变化。当指定的值发生变化时,onChange 会执行提供的代码块。
使用场景
在 SwiftUI 中,.onAppear 只会在视图首次加载时被触发,但有时可能希望在某个状态值(如布尔值、变量等)发生变化时执行特定操作。这时就可以使用 .onChange。
假设有一个 @State 变量 isActive,希望在 isActive 变为 true 或 false 时执行一些操作:
@State private var isActive: Bool = false
var body: some View {
VStack {
Toggle("Activate", isOn: $isActive)
.padding()
}
.onChange(of: isActive) { oldValue, newValue in
if newValue {
print("isActive 切换为 true,执行某些操作")
} else {
print("isActive 切换为 false,执行其他操作")
}
}
}
在这个例子中,每当 isActive 的值改变时,onChange 的闭包都会被调用,newValue 会是 true 或 false。
问题报错
在使用onChange的过程中可能存在如下报错:
'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.
这是因为onChange的一个形式被标记为废弃。
背景与废弃的 onChange() 变体
在 iOS 16 及更早版本中,onChange 有以下三种常见形式:
1、接受旧值和新值的完整形式(推荐形式,从 iOS 14 开始支持):
.onChange(of: someValue) { oldValue, newValue in
// 响应变化,并可使用旧值和新值
}
2、只接受新值的简化形式(被标记为废弃,从 iOS 17 开始不建议使用):
.onChange(of: someValue) { newValue in
// 响应变化,只使用新值
}
3、不接受参数的形式(适用于只关心变化但不需要新值的场景):
.onChange(of: someValue) {
// 响应变化,不需要访问值
}
Apple 从 iOS 17 开始废弃了第二种只接受新值的形式。废弃的原因是开发者往往需要同时访问旧值和新值,而简化形式可能导致不必要的限制。
替代方案
Apple 并没有提供新的替代方案,因为第一种形式(接受旧值和新值)已经能够满足所有需求,同时保留了灵活性。因此,推荐使用以下形式:
.onChange(of: someValue) { oldValue, newValue in
// 使用旧值和新值执行逻辑
}
如果并不需要旧值,只关心新值,也可以忽略旧值的使用:
.onChange(of: someValue) { _, newValue in
print("New value is \(newValue)")
}
是否可以继续使用已废弃的形式?
向后兼容性:如果需要支持 iOS 16 及更早版本,仍然可以使用废弃的形式。这种形式在旧版本中是完全可用的。
未来支持风险:废弃的形式在未来可能被完全移除,因此对于只面向 iOS 17+ 的应用,不建议继续使用这种形式。
废弃的形式仍然可以正常工作,但为了确保代码的可维护性,最好迁移到推荐形式。