如何合并ObservableObject多次变更,仅发送一次objectWillChange通知?
在Swift中将ObservableObject的多次属性变更合并为单次发布通知
我有一个包含@Published可变变量的ObservableObject类,在某个函数中会多次修改该类的属性值。现在需要将这些分散的变更合并为一个事务,让objectWillChange发布者仅发送一次通知,避免多次触发更新。
示例代码
struct MyDataModel { var t1: String = "" var t2: String = "" var t3: String = "" } class MyOO: ObservableObject { @Published var data: MyDataModel = MyDataModel() func mutateData() { // 在此方法中合并所有变更 data.t1 = "1" data.t2 = "12" data.t3 = "123" } } let myoo = MyOO() _ = myoo.objectWillChange.sink { print(myoo.data) } myoo.mutateData()
当前输出
MyDataModel(t1: "", t2: "", t3: "") MyDataModel(t1: "1", t2: "", t3: "") MyDataModel(t1: "1", t2: "12", t3: "")
期望输出
MyDataModel(t1: "1", t2: "12", t3: "")
直接复制@Published变量的值、修改后再赋值回去的方法需要大量代码改动,希望找到更简洁、符合Swift习惯的实现方式。
解决方案
方法1:手动控制objectWillChange发送时机
在批量修改前手动发送一次objectWillChange通知,后续修改结构体属性时,@Published的自动通知会被抑制,所有变更合并为一次发布:
func mutateData() { objectWillChange.send() data.t1 = "1" data.t2 = "12" data.t3 = "123" }
方法2:自定义withTransaction扩展(推荐)
给ObservableObject添加通用扩展,封装事务逻辑,让批量修改代码更整洁且复用性强:
extension ObservableObject { func withTransaction(_ block: () -> Void) { objectWillChange.send() block() } }
使用时将所有变更包裹在闭包中:
func mutateData() { withTransaction { data.t1 = "1" data.t2 = "12" data.t3 = "123" } }
方法3:直接生成新结构体实例赋值
利用结构体的值类型特性,一次性生成修改后的新实例赋值给@Published变量,自然只会触发一次通知:
func mutateData() { data = MyDataModel(t1: "1", t2: "12", t3: "123") }
如果结构体属性较多,可通过复制语法保留原有属性值:
func mutateData() { data = MyDataModel( t1: "1", t2: "12", t3: "123", t4: data.t4 // 保留原有属性值 ) }
内容的提问来源于stack exchange,提问作者Aswath
相关产品推荐
相关产品推荐

