You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:53:26