技术探索与实践的五年成长路:从“搬砖”到“造砖”
刚入行的时候,我总觉得技术就是解决问题的能力。写代码、调接口、改 Bug 就是全部。那时候每天都在想着怎么把产品经理的需求“翻译”成代码,很少停下来去想,“为什么这么做?”、“有没有更好的方式?”。直到几年后,我在一个大型项目中经历了架构升级、性能优化、跨团队协作等多个挑战,我才真正理解了什么是“技术探索与实践”。
今天我想借这篇文章,结合自己这几年的经历,尤其是最近参与的一个重要项目,聊聊我对这个话题的看法。
背景:一次性能翻车事件

2019年我加入了一家电商类创业公司,当时的产品已经上线一年多了,用户量也逐步上涨。但由于早期开发节奏快、产品需求急,导致底层架构和模块划分并不清晰。随着业务不断增长,App 出现了一些不可忽视的问题,比如:
- 首屏加载慢
- 列表滑动卡顿
- 多人协作容易冲突
- 模块复用性差
有一次我们做了一个促销活动页面,结果上线当天用户一多,就开始出现大量 Crash 和 ANR(Application Not Responding)。这成了我职业生涯中的一个转折点,也是促使我去深入思考“技术探索”的起点。
问题:如何让 App 更流畅、更稳定?

面对这些问题,我们团队开始了一场“技术反思大会”,目标很明确:
- 提升用户体验(流畅度、稳定性)
- 提高代码可维护性(降低后期迭代成本)
- 构建一套可复用的技术方案(方便后续新业务快速接入)
当时的 iOS 开发主流还在使用 MVC 结构,但我们发现 ViewController 中堆积了大量的业务逻辑,甚至有些文件有上千行代码,完全无法阅读。UI 层、数据层、网络层严重耦合,修改任何一处都要小心翼翼,生怕牵一发动全身。
于是我们决定启动一项名为 Project Athena 的架构重构项目,希望通过这次机会引入 MVVM+Coordinator 模式,并在性能方面下一番功夫。
解决方案:架构重构 + 性能优化并行推进

1. 架构设计选择:MVVM + Coordinator
我们选择了 MVVM 作为视图层的架构模式,配合 Coordinator 来管理导航逻辑。
📌 为什么要这样选?
MVC 是苹果官方推荐的,但实际开发中往往会造成 Massive View Controller;而 MVP 虽然解耦性强,但在 iOS 上实现比较繁琐;MVVM 更加适合 Swift + Combine/ViewModel 的响应式编程风格。加上 Coordinator 可以很好地管理跳转逻辑和生命周期,非常适合我们这种需要高度组件化、流程复杂的 App。
我们在项目中引入了如下结构:
├── Feature
│ ├── Home
│ │ ├── HomeViewController.swift
│ │ ├── HomeViewModel.swift
│ │ └── HomeCoordinator.swift
│ └── ProductDetail
│ ├── ProductDetailViewController.swift
│ ├── ProductDetailViewModel.swift
│ └── ProductDetailCoordinator.swift
├── Core
│ ├── NetworkManager.swift
│ └── PersistenceManager.swift
└── Shared
└── CommonUIComponents.swift
每个功能模块都有自己的 Coordinator 负责导航流转,ViewModel 管理 UI 数据绑定,View 只负责渲染。大大降低了 ViewController 的复杂度。
2. 使用 SwiftUI 替代部分 UIKit 页面
为了进一步提升效率和可维护性,我们在一些新的业务线中尝试引入 SwiftUI。最初团队很多人不习惯声明式语法,甚至觉得写起来不如 UIKit 直接。
但经过几周磨合,大家发现:
- 布局代码减少了很多
- 实时预览调试效率极高
- Binding、State、ObservedObject 这些机制特别适合做状态管理
- 动画效果实现更加优雅简洁
后来我们做了个对比实验:两个工程师分别用 UIKit 和 SwiftUI 写一个相似的商品详情页,结果 SwiftUI 用时更短、出错更少,而且测试反馈说交互逻辑更容易理解。
3. 性能优化方向:内存 & 渲染优先级控制
除了架构层面的调整,我们还做了几个重点性能优化:
(1) 图片懒加载 & 缓存策略优化
早期使用的 SDWebImage 已经很成熟,但我们发现某些图片请求并没有合理缓存,尤其是在商品列表页频繁滑动时,会出现重复加载的情况。
我们做了以下优化:
- 自定义缓存 Key,确保相同 URL 不会重复加载
- 控制并发请求数,避免主线程阻塞
- 滑动时暂停非可视区域的图片加载,停止滑动后再恢复
func configureImage(for url: URL?) {
guard let url = url else { return }
if isCellVisible {
imageView.sd_setImage(with: url, completed: nil)
} else {
// 滑动中不加载图片
imageView.image = UIImage(named: "placeholder")
}
}
(2) 使用 Instruments 定位内存泄漏
通过 Instruments 的 Leaks 工具,我们发现了多个强引用循环,特别是在 Delegate、NotificationCenter、Timer 等地方没有及时释放。
解决办法包括:
- 引用代理使用
weak - Timer 使用
scheduledTimer并设置repeats: false - 在 Deinit 中取消所有观察者注册
(3) 启用 App Thinning 和 Bitcode
为了让安装包大小控制得更好,我们启用了 App Thinning 和 Bitcode,根据设备类型自动分发最合适的二进制文件。这对冷启动速度也有明显帮助。
踩过的坑和经验总结

坑1:过度设计导致初期效率下降
在项目初期,我们曾试图用协议驱动一切,甚至连 ViewModel 的数据源也全靠 Protocol 去抽象,结果导致:
- 模板代码过多,学习成本高
- 编译时间变长
- 团队新人上手困难
后来我们做了一些精简,比如不再强制所有数据都走泛型或协议,而是只在真正需要解耦的地方才使用。回归“适度设计”的原则。
坑2:SwiftUI 与 UIKit 混编带来的兼容性问题
在混合使用 SwiftUI 和 UIKit 时,我们遇到了以下几个问题:
UIViewControllerRepresentable包装的控制器有时不会正确释放- 导航栈混用
UINavigationController和NavigationStack时行为不一致 - 生命周期控制变得复杂
最后我们选择统一使用 SwiftUI(因为大部分业务是新做的),对遗留的 UIKit 页采用桥接方式慢慢过渡。
坑3:异步任务处理不当导致崩溃
有一次上线后收到很多崩溃报告,定位后发现是某个异步回调中访问了已经被释放的对象。
我们的解决方案是:
- 所有异步回调使用
[weak self]捕获上下文 - 使用 OperationQueue 替代 GCD 做任务调度,便于管理依赖关系
- 对于关键路径使用断言检测是否为主线程执行
效果与收益
经过三个月的重构和优化,我们的 App 在多个维度都有显著提升:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 首屏加载时间 | 3.5s | 2.1s |
| ANR / Crash 率 | 0.8% | 0.1% |
| 新功能开发周期 | 平均 4 周 | 缩短至 2.5 周 |
| 单个 ViewController 平均行数 | 800+ 行 | 200 行以内 |
更重要的是,团队的协作效率提升了,文档更清晰了,新成员可以更快地理解架构逻辑和编码规范。
我的几点建议

如果你也在经历类似的困境或者想要做一次技术跃迁,下面是我这几年踩坑总结出来的几点建议:
✅ 1. 不要为“设计模式”而设计模式
设计模式不是银弹,它只是手段。不要为了看起来高级而去强行套用 MVVM 或 VIPER,先搞清楚你的需求边界在哪里,再考虑该不该拆解、如何拆解。
✅ 2. 技术探索必须结合业务场景
脱离业务的技术升级就像空中楼阁,很快就会被打回原形。每次技术方案制定前,一定要问自己:“这个改动能给业务带来什么价值?”
✅ 3. 经常回顾和反思自己的代码习惯
我以前喜欢在 ViewController 里写一堆 extension 分隔方法,以为这样就能解耦。其实只是视觉上的整洁而已,本质还是 MVC 的臃肿。定期 review 自己的代码,看看有没有更好的写法,才能持续进步。
✅ 4. 学会使用工具定位问题
Instruments、Xcode 的 Memory Debugger、Thread Sanitizer 这些工具真的能帮你省下大量排查时间。别总想着靠日志打印来调试问题。
✅ 5. 保持对新技术的好奇心,但要理性判断时机
现在 SwiftData、Async/Await、TCA 架构等新兴技术层出不穷。我鼓励大家去了解、去试水,但不一定马上在主业务线上使用。可以在 side project 或内部 demo 项目中先行验证,确认其适用性和稳定性。
最后的感悟:技术是为了解决问题,更是为了创造可能性
回头来看,五年 iOS 开发让我明白一个道理:技术从来都不是最终目的,而是实现目标的工具。你掌握了多少种设计模式、写了多少行代码都不重要,重要的是你能不能用这些技术做出对用户有意义的产品。
我也从“照着文档写代码”的新手,成长为“能主动提出问题、设计方案”的开发者。技术探索的过程虽然很痛苦,但正是这些痛苦让我成长得更快。
希望这篇文章能给你带来一点启发。如果你正在面临类似的架构难题、性能瓶颈、团队协作问题,不妨静下心来,好好梳理一下业务逻辑和技术现状,找到属于自己的“最优解”。
共勉!🌟

评论 0