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
相关产品推荐
相关产品推荐

