SwiftUI onChange监听异常:MCReceiveItem属性值反复切换问题
问题核心:值类型与引用类型在@Observable中的行为差异
这个问题完全是结构体和类的底层特性,加上@Observable的变更追踪逻辑共同导致的,具体拆解:
结构体值类型的实例替换特性
MCReceiveItem作为结构体(值类型),你修改它的isFinished属性时,本质是生成了一个全新的结构体实例,再把这个新实例赋值回MCService的receiveItem。如果SwiftUI视图的更新周期和这个赋值操作的时机没对齐,视图可能会在更新过程中短暂读取到旧的结构体副本(isFinished=false),就会出现你看到的false→true→false→true跳变——新实例触发true,旧副本又临时显示false,最后同步到新实例的true。@Observable对值/引用类型的追踪逻辑不同
@Observable是靠监听属性setter来发变更通知的:- 对结构体这类值类型,只有整个实例被替换(也就是
receiveItem的setter被调用)时才会触发通知。修改结构体内部属性本身不会直接触发通知,必须重新赋值整个实例,这就很容易出现状态同步的间隙。 - 对class这类引用类型,修改内部属性不需要替换整个实例,@Observable可以直接追踪到内部属性的变更,所有引用指向同一个实例,状态不会出现分裂,自然不会有跳变问题。
- 对结构体这类值类型,只有整个实例被替换(也就是
隐式副本导致的状态分裂
结构体在传递、赋值时会自动复制,如果你的代码里有多个地方持有receiveItem的副本,这些副本的状态不会自动同步。SwiftUI视图如果在不同时机读取到不同的副本,就会出现状态反复的情况。而class是引用类型,所有地方都指向同一个实例,状态是统一的。
内容的提问来源于stack exchange,提问作者雷子康
相关产品推荐
相关产品推荐

