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

iOS(含KMM iOS端)MVVM架构下ViewModel内Task的取消问题

在iOS/KMM Swift开发的MVVM架构中,ViewModel内部Task的取消问题

核心疑问

在iOS(或KMM的iOS端)采用MVVM架构进行Swift开发时,有两个核心疑问:

  • ViewModel内部创建的Task是否需要手动取消?还是iOS会自动处理?
  • 若需手动取消,正确的时机是什么?比如针对示例中的eligibilityCheckJob,可选的两个位置:
    • AppInitViewModel的deinit()方法
    • AppInitScreen视图的onDisappear()方法(该方法会调用ViewModel的onCleared())

我在模拟器中分别测试了「手动取消」和「不取消」两种场景,均未检测到内存泄漏。

尝试的中间方案:基于View的.task修饰符扩展

最初参考建议考虑使用View的.task修饰符,它能自动跟随视图生命周期管理任务取消,但我希望异步逻辑保留在ViewModel中,于是编写了如下扩展函数,想确认这种方式是否可行且不破坏MVVM模式:

extension AppInitScreen {
    /// 通过视图的.task修饰符启动任务,任务会跟随视图生命周期自动取消,适用于无需跟踪的一次性任务
    func launchTask(priority: TaskPriority = .userInitiated, _ action: @escaping @Sendable () async -> Void) -> some View { // 需要导入SwiftUI
        return self.task(priority: priority, action)
    }
    
    class AppInitScreen: ObservableObject, AppInitScreenStateIListener {
        //...
        @MainActor
        private func processEligibilityCheck() {
            screenView.launchTask {
                //...
                isInternetAvailable = try await networkService.isInternetAvailable()
            }
        }
    }
}

最终确定的方案

后续发现上述方案存在问题:需要将View实例传递给ViewModel,这违背了MVVM架构中「ViewModel不依赖View」的原则;同时我的任务是通过按钮点击触发,而非视图出现时自动执行,因此放弃了.task修饰符方案,最终采用以下策略:

  • 长时间运行的任务:在视图的onDisappeared()方法中触发ViewModel的onCleared(),并在该方法内手动取消任务;
  • 短运行任务:无需额外处理,任务完成后会自动结束,不会引发内存问题。

内容的提问来源于stack exchange,提问作者Petr Apeltauer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:20:07