初始化@State属性导致SwiftUI应用冻结,求问题排查方案
问题分析与解决方案
问题根源
应用挂起的核心原因是错误地用@State包装引用类型(ChildViewModel这个@Observable类),且手动初始化State的方式违反了SwiftUI状态管理规则:
@State是为值类型设计的状态容器,负责值的持久化和视图刷新触发。而引用类型(类)实例存储在堆上,@State无法正确管理其生命周期,极易引发无限视图刷新循环,最终阻塞主线程导致应用挂起。- 手动写
_viewModel = State(initialValue: ChildViewModel())的初始化逻辑,干扰了SwiftUI内部的状态存储机制,触发了异常的视图更新流程。
修复方案
针对你的场景,有两种合规的实现方式:
方式1:用@StateObject管理Observable类(推荐)
因为ChildViewModel是@Observable类,应该使用@StateObject来包装——它专门负责管理引用类型Observable对象的生命周期:
struct ChildView: View { @StateObject private var viewModel = ChildViewModel() var body: some View { Text("Hello, World!") } }
@StateObject会在视图初始化时创建唯一的ViewModel实例,并在整个视图生命周期内保持稳定,避免重复创建和异常刷新。- 无需手动编写
init方法,SwiftUI会自动处理初始化逻辑。
方式2:改用值类型ViewModel(如果不需要Observable)
如果你的ViewModel不需要响应式能力(当前代码为空),可以将其改为结构体(值类型),再用@State包装:
struct ChildViewModel { // Empty } struct ChildView: View { @State private var viewModel = ChildViewModel() var body: some View { Text("Hello, World!") } }
原代码挂起的具体原因
当用@State包装引用类型并手动初始化State时,SwiftUI的视图更新机制会陷入混乱:每次视图渲染时可能重复创建State实例,或者因引用类型的引用计数变化触发无限的视图刷新循环,最终导致主线程被完全阻塞,应用失去响应。移除ViewModel后,视图没有了异常的状态更新触发,自然恢复正常。
内容的提问来源于stack exchange,提问作者Brandon Stillitano
相关产品推荐
相关产品推荐

