如何为@StateObject设置带有可抛出init()的对象?
为@StateObject设置带可抛出init的对象的解决方案
问题原因
@StateObject的wrappedValue参数接收的是非抛出自动闭包,直接调用会抛出错误的MyObject()时,就会触发你遇到的Call can throw, but it is executed in a non-throwing autoclosure错误。
解决方案
方案1:使用可选类型的@StateObject,结合do-catch初始化
将@StateObject声明为可选类型,在视图的init中通过do-catch处理抛出逻辑,成功创建实例后赋值给底层的StateObject存储:
class MyObject: ObservableObject { init() throws { // 带抛出逻辑的初始化代码 guard true else { throw NSError(domain: "Test", code: 0) } } } struct ContentView: View { @StateObject private var myObject: MyObject? init() { do { let object = try MyObject() _myObject = StateObject(wrappedValue: object) } catch { // 处理初始化失败的情况,比如打印错误或设置默认值 print("初始化MyObject失败:\(error)") } } var body: some View { Text(myObject != nil ? "初始化成功" : "初始化失败") } }
方案2:用工厂方法封装抛出逻辑,返回非可选实例
创建一个工厂方法,在内部处理抛出逻辑,确保返回一个有效的实例(比如捕获错误后返回默认实例),这样就能安全地赋值给@StateObject:
class MyObject: ObservableObject { init() throws { guard true else { throw NSError(domain: "Test", code: 0) } } // 工厂方法 static func create() -> MyObject { do { return try MyObject() } catch { // 捕获错误后返回默认实例,或者根据需求处理 return MyObject(defaultValue: "默认值") } } // 用于创建默认实例的初始化方法 init(defaultValue: String) { // 默认初始化逻辑 } } struct ContentView: View { @StateObject private var myObject = MyObject.create() var body: some View { Text("已初始化") } }
方案3:在视图外部提前创建实例,再传入视图
如果允许在视图初始化前处理实例创建,可以先在父视图或其他地方完成抛出逻辑,将创建好的实例传入当前视图:
struct ParentView: View { var body: some View { do { let object = try MyObject() ContentView(myObject: object) } catch { Text("创建实例失败") } } } struct ContentView: View { @StateObject private var myObject: MyObject // 接收外部传入的实例 init(myObject: MyObject) { _myObject = StateObject(wrappedValue: myObject) } var body: some View { Text("初始化成功") } }
内容的提问来源于stack exchange,提问作者user21757794
相关产品推荐
相关产品推荐

