SwiftUI中类引发循环引用:如何解决视图无法销毁的问题
打破SwiftUI中View与ObservableObject的循环引用方案
针对你遇到的循环引用问题,这里提供几种可行的解决方案:
方案一:在View消失时清空闭包引用
利用onDisappear回调,在View即将销毁时清空MyObject中持有的闭包,直接打破循环链:
class MyObject: ObservableObject { var function = { () } } struct MyView: View { @State var value: Int = 0 @StateObject var obj = MyObject() func viewMethod() { value += 1 } var body: some View { Text("Placeholder") .onAppear { obj.function = { self.viewMethod() } } .onDisappear { // 清空闭包,解除对View的引用 obj.function = {} } } }
这种方式简单直接,适合View和MyObject生命周期绑定的场景(比如MyObject由@StateObject管理,和View同生共死)。
方案二:使用无主引用(Unowned)捕获View
因为@StateObject管理的MyObject生命周期和View完全一致,不会出现View已销毁但MyObject还存在的情况,所以可以用unowned修饰捕获的self,避免闭包强引用View:
class MyObject: ObservableObject { var function = { () } } struct MyView: View { @State var value: Int = 0 @StateObject var obj = MyObject() func viewMethod() { value += 1 } var body: some View { Text("Placeholder") .onAppear { // 用unowned self避免强引用 obj.function = { [unowned self] in self.viewMethod() } } } }
注意:仅当你能确保闭包调用时View一定存在的情况下使用unowned,否则可能触发崩溃。
方案三:将View逻辑转移到独立ViewModel类
如果View中的业务逻辑复杂,可将需要触发的方法和状态转移到独立的ViewModel类中,通过弱引用捕获ViewModel来打破循环:
class MyObject: ObservableObject { var function = { () } } // 独立ViewModel类,管理View的状态和方法 class ViewModel: ObservableObject { @Published var value: Int = 0 func viewMethod() { value += 1 } } struct MyView: View { @StateObject var vm = ViewModel() @StateObject var obj = MyObject() var body: some View { Text("Placeholder") .onAppear { // 弱引用捕获ViewModel,避免循环 obj.function = { [weak vm] in vm?.viewMethod() } } } }
这种方式隔离了View和业务逻辑,同时通过weak vm避免了强引用循环,适合更复杂的场景。
内容的提问来源于stack exchange,提问作者bodich
相关产品推荐
相关产品推荐

