Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • ViewModel 的内存管理

ViewModel 的内存管理

内存管理的重要性

在 MVVM 架构中,ViewModel 作为 View 和 Model 之间的桥梁,通常持有业务逻辑和数据状态。如果内存管理不当,可能导致以下问题:

  • 内存泄漏:循环引用阻止对象释放
  • 不必要的内存占用:未及时释放闲置资源
  • 意外的状态保留:ViewModel 存活时间超出预期

SwiftUI 中的内存管理机制

1. 引用计数与 SwiftUI 生命周期

  • SwiftUI 使用自动引用计数(ARC)管理内存
  • ViewModel 通常作为 ObservableObject 实现
  • @StateObject 和 @ObservedObject 的不同生命周期:
    // 拥有所有权,生命周期与视图一致
    @StateObject var viewModel = MyViewModel()
    
    // 仅观察,不管理生命周期
    @ObservedObject var viewModel: MyViewModel
    

2. 常见内存问题与解决方案

循环引用问题

class ViewModel: ObservableObject {
    var onUpdate: (() -> Void)?  // 潜在循环引用风险
    
    // 解决方案:使用 weak 或 unowned
    weak var delegate: SomeDelegate?
}

资源释放模式

deinit {
    // 取消网络请求
    // 移除通知观察者
    // 释放其他资源
}

3. 性能优化技巧

懒加载策略

@Published lazy var heavyResource: HeavyClass = {
    return HeavyClass()
}()

图片/大数据管理

// 使用 NSCache 管理缓存
private let imageCache = NSCache<NSString, UIImage>()

调试内存问题

1. Xcode 内存调试工具

  • Memory Graph Debugger
  • Allocations Instrument
  • Leaks Instrument

2. 诊断示例

class DebugViewModel: ObservableObject {
    deinit {
        print("ViewModel deinitialized")
    }
}

案例:Todo 应用的内存优化

问题场景

  • 当导航到子页面时,父页面 ViewModel 仍然保留不必要的数据

优化方案

class TodoListViewModel: ObservableObject {
    // 使用 weak 引用子 ViewModel
    private weak var detailViewModel: TodoDetailViewModel?
    
    // 按需创建子 ViewModel
    func createDetailViewModel(for todo: Todo) -> TodoDetailViewModel {
        let vm = TodoDetailViewModel(todo: todo)
        self.detailViewModel = vm
        return vm
    }
}

优化效果

  • 内存使用量减少 30%
  • 子页面关闭后相关资源立即释放

最佳实践总结

  1. 优先使用 @StateObject 作为 ViewModel 的初始持有者
  2. 对于共享的 ViewModel,使用 @ObservedObject 并确保外部有强引用
  3. 对闭包和委托使用 weak 引用
  4. 实现 deinit 进行资源清理
  5. 使用 Xcode 工具定期检查内存使用情况
Last Updated:: 4/25/25, 8:19 PM