SwiftUI:如何实现仅在视图完全移除时触发一次的onUnLoad修饰器
实现SwiftUI中仅触发一次的onUnLoad修饰器
当然可以实现仅在视图被完全移除时触发一次的onUnLoad修饰器,核心思路是利用SwiftUI中@StateObject的生命周期绑定特性——当视图被彻底从层级结构中移除时,@StateObject持有的对象会被销毁,我们可以在对象的销毁方法中执行卸载逻辑。
完整实现代码
import SwiftUI extension View { /// 仅在视图被完全移除时触发一次的卸载回调 /// - Parameter action: 视图被销毁时要执行的逻辑 func onUnLoad(perform action: @escaping () -> Void) -> some View { self.modifier(ViewUnloadModifier(action: action)) } } /// 处理卸载逻辑的辅助类,在实例被销毁时触发传入的动作 private class UnloadHandler { private let action: () -> Void init(action: @escaping () -> Void) { self.action = action } deinit { action() } } /// 绑定卸载逻辑的视图修饰器 private struct ViewUnloadModifier: ViewModifier { private let action: () -> Void init(action: @escaping () -> Void) { self.action = action } func body(content: Content) -> some View { content .stateObject(UnloadHandler(action: action)) } }
原理说明
UnloadHandler是一个轻量级类,仅持有要执行的卸载动作,在其deinit(实例销毁)方法中触发动作。ViewUnloadModifier使用@StateObject来持有UnloadHandler实例,@StateObject的生命周期会严格绑定到当前视图:- 视图首次出现在层级中时,
@StateObject会创建UnloadHandler实例; - 视图被暂时隐藏(如Tab切换、导航栈临时弹出)时,
@StateObject实例不会被销毁,因此不会触发卸载动作; - 视图被完全移除(如导航栈弹出后不再返回、条件渲染的视图被切换为隐藏)时,
@StateObject实例会被销毁,自动执行deinit中的卸载逻辑,且只会触发一次。
- 视图首次出现在层级中时,
示例用法
struct MyView: View { var body: some View { Text("Hello View") .onDisappear { // 视图暂时隐藏或被移除时都会触发,可能多次打印 print("onDisappear") } .onUnLoad { // 仅在视图被完全销毁时打印一次 print("onUnLoad") } } }
内容的提问来源于stack exchange,提问作者flopshot
相关产品推荐
相关产品推荐

