资讯详情

十年iOS开发实战总结:从Objective-C到SwiftUI的技术演进与踩坑指南

📅 2026/9/24 8:34:35 | 华诺云谱 👁 阅读
十年iOS开发实战总结:从Objective-C到SwiftUI的技术演进与踩坑指南
1. 项目概述十年iOS开发我到底在坚持什么“Ioser 铭”这个名字是我在2015年刚入行iOS开发时起的。那时候觉得自己特立独行非要给开发者身份加个后缀显得与众不同。十年过去这个“铭”字反倒成了某种隐喻——像是刻在石碑上的记号记录着一个普通iOS开发者从懵懂到成熟的全过程。2015年的iOS开发圈和现在完全是两个世界。那时候Swift刚发布一年大家都在Objective-C和Swift之间反复横跳Xcode还停留在7.x版本动不动就崩溃iPhone 6s刚出来适配它的屏幕尺寸成了全民话题。我当时在一家小公司做移动端负责人带着两个初级开发从零开始搭建一个电商App的iOS端。没什么高大上的架构就是MVC加Storyboard网络层用AFNetworking数据解析用MJExtension那时候能把这套组合玩明白就已经算合格的上岗iOS开发了。一转眼到了2025年十年时间我换了四家公司做过电商、社交、工具类、教育类App从普通开发做到技术专家面试过几百个iOS开发者也被面试过无数次。回头看这十年iOS开发这个领域的变迁其实可以浓缩成几条清晰的主线语言从Objective-C到Swift再到SwiftUI架构从MVC到MVVM再到Composable Architecture工具链从Xcode独占到CocoaPods、SPM并存生态从纯粹的iOS延伸到iPadOS、macOS、watchOS、visionOS全平台覆盖更不用说跨平台方案从React Native到Flutter以及后来异军突起的uni-app和鸿蒙。这篇文章我想以一个亲历者的视角把这十年走过的路、踩过的坑、攒下的经验原原本本分享出来。不管你是刚入行的小白还是已经有几年经验的开发者我相信里面总有一些东西对你有用。毕竟iOS开发的门槛其实不高但天花板极高很多细节和心得是文档和教程里根本不会写到的。2. 从Objective-C到Swift再到SwiftUI语言演进的底层逻辑2.1 Objective-C时代动态运行时是怎么撑起一个生态的2015年入行的iOS开发者绝大多数是从Objective-C起步的。这门语言放在今天看语法确实怪方括号嵌套方括号方法名长得能占满一整行。但它有一个至今都让很多语言汗颜的能力动态性。Objective-C的运行时机制允许你在程序运行的时候往类里添加方法、交换方法实现、动态创建类。这意味着你可以做很多“越界”的事情。比如Method Swizzling可以把系统方法替换成自己的实现这在埋点统计、AOP切面编程里几乎是标配。再比如Associated Object可以给系统类动态挂载属性很多第三方库都靠这个实现。我当时做的一个网络监控组件就是用Swizzling去hook了NSURLSession的请求方法把所有网络请求的耗时、状态码、响应体全部记录下来上报到后端做性能分析。这个方案在Objective-C时代非常成熟几乎每个大厂App里都藏着一堆Swizzling代码。但动态性带来的代价也显而易见。方法调用走的是消息转发机制比直接函数调用慢类型检查发生在运行时很多错误要到崩溃才能发现而且代码可读性差block嵌套多层之后新手基本看不懂。Objective-C的另一个痛点是字符串拼接式的API设计。比如[NSString stringWithFormat:%_%d, name, age]这种写法拼错一个占位符类型编译期不报错运行时就崩了。尤其做数据模型解析的时候字典取key、转类型、判空这一套写下来代码量大且极易出错。2.2 Swift的崛起为什么说它不只是“换了层皮”2014年苹果发布Swift的时候很多人觉得这就是一个“更现代的Objective-C”。但真正用过之后你会发现Swift的变化是革命性的。它不只是改了语法而是从根本上改变了写代码的方式。最核心的变化是安全性的提升。Swift引入了Optional机制从语言层面强制开发者处理空值问题。这在当年是一个巨大的进步因为Objective-C时代最普遍的崩溃原因就是向nil对象发消息。Optionals配合if let和guard let让很多潜在的空指针问题在编译期就被拦截了。我记得Swift 2.0时代团队里有个同事因为不习惯Optionals写代码经常一大串!强制解包结果测试阶段天天崩溃。后来我定了一个规则代码评审时看到强制解包必须说明理由否则打回重改。这个规则执行了两个星期崩溃率肉眼可见地降下来了。Swift的价值还体现在值类型和引用类型的区分上。Struct、Enum这些值类型默认是拷贝语义避免了多线程环境下的数据竞争问题。后来的SwiftUI更是把值类型的思想贯穿到了整个UI框架里。对比Objective-C时代一个可变字典在不同线程之间传来传去稍不注意就崩得莫名其妙Swift这种方式确实让人安心很多。还有一个不能忽视的推动力是Swift开源了。开源意味着你能看到编译器源码能在Linux上跑Swift代码也意味着社区可以自由地为Swift贡献代码。Swift Package Manager基于开源生态快速发展到2019年左右基本达到了可以替代CocoaPods的水平。现在的新项目我基本只依赖SPMCocoaPods只在接手老项目时才会碰到。2.3 SwiftUI声明式UI带来的思维转变SwiftUI在2019年的WWDC上发布当时我正好在做一个新App的架构选型。说实话第一版SwiftUI只能用“能跑但不好用”来形容支持的iOS版本最低要到13很多高级控件缺失性能也有问题。我们评估了两周最终决定还是在老项目用UIKit只是小范围尝试SwiftUI。后来SwiftUI经过几个大版本的迭代到iOS 16、17的时候已经相当成熟了。声明式UI的核心理念是你描述“界面应该长什么样”而不是“如何一步步把界面画出来”。这听起来抽象但对比一下代码就明白了。用UIKit写一个列表你需要创建UITableView、设置dataSource和delegate、实现cellForRowAt方法、处理重用机制。用SwiftUI写同样的列表几行代码就够了struct ContentView: View { let items [Apple, Banana, Orange] var body: some View { List(items, id: \.self) { item in Text(item) } } }这种差异背后本质上是状态管理思路的变化。UIKit时代界面是“事件驱动”的你监听按钮点击、网络回调然后手动更新UI。SwiftUI是“状态驱动”的UI只是状态的函数状态变了UI自动跟着变。这个思想极大减少了样板代码也让状态一致性变得更容易保证。不过我还是要说一句得罪人的话SwiftUI目前还不能完全替代UIKit。复杂交互场景比如嵌套滚动、自定义转场、高效的列表性能优化这些还是得靠UIKit来兜底。我的做法是新页面优先用SwiftUI遇到复杂需求用UIViewRepresentable和UIViewControllerRepresentable嵌入UIKit组件。这套“SwiftUI为主体 UIKit为补充”的混合模式算是目前比较务实的方案。3. 面试了上百个iOS开发者我最看重什么3.1 基础功底筛掉六成候选人的是第一题我参与面试的几百场中有一个必问题weak和assign有什么区别就这一个问题能淘汰掉接近六成的候选人。很多人知道weak用于避免循环引用但真正能讲清楚底层原理的并不多。weak修饰的属性在对象释放后会自动置为nil避免野指针。它的实现机制是Objective-C的SideTable表系统用一张全局的Hash表维护了所有weak指针的地址和对象地址的对应关系对象释放时会通过这张表找到所有指向它的weak指针统一置为nil。assign就没有这个待遇它只是简单的指针赋值。它本来用于修饰基本数据类型因为基本类型存储在栈上不会有释放的问题。但有些人用assign修饰对象对象释放后指针还指向原来的内存地址就成了野指针下次访问直接崩溃。这个问题既考察基础知识又考察底层原理还能顺便看看面试者平时写代码有没有思考习惯一题三用。另一个高频考点是copy和strong的区别。NSString用copy修饰是为了防止可变字符串被外部修改NSArray、NSDictionary同理。但很多人在自定义模型时属性全部用strong这就埋了隐患。面试时我会追问如果你用strong修饰了一个NSArray属性外部传入一个NSMutableArray会怎么样能答出“外部修改会引发不可预知问题”的候选人基础基本是扎实的。3.2 多线程和内存管理闯过大厂面试的必过关iOS开发中多线程是永远绕不开的话题。GCD、OperationQueue、NSThread以及Swift的async/await每个阶段都有不同的主流方案。面试官最爱问的问题是DispatchQueue.main.async和DispatchQueue.main.sync有什么区别为什么sync会导致死锁这个问题的坑在于很多人知道sync不能在主线程调用但不知道为什么。深入一点说main.sync把同步任务提交到主线程队列然后阻塞当前线程等待执行完毕而主线程此时正在执行这段代码也在等待sync返回——两个线程互相等待就死锁了。这个例子很好地考察了候选人对GCD队列原理的理解程度。内存管理是另一个重点。ARC的引入虽然省了很多心但循环引用问题仍然常见。block的循环引用、NSTimer的循环引用、delegate是strong导致的循环引用这三大件几乎是面试必考。现在用Swift闭包捕获列表的写法也要能熟练运用。我记得有个候选人能熟练说出[weak self]和[unowned self]的区别但当我问到“如果self在闭包执行期间已经被释放这两种写法的崩溃场景分别是什么”时就答不上来了。其实答案很简单weak是optional访问时是nil不会崩unowned是非optional访问时相当于强制解包会崩。这个细节在实际编码中非常关键尤其在做异步操作时稍不注意就是线上事故。3.3 项目经验怎么聊鉴别真实与包装很多候选人简历写得天花乱坠项目经验五六段每一段都用了各种高深技术。但只要细问几个细节真假立判。我的做法是挑一个候选人最熟悉的项目让他从头到尾讲一遍架构设计。真实做过项目的开发能清晰地说出为什么要选这个方案数据流怎么走遇到什么问题又怎么调整。包装出来的候选人只能背出一些概念一到细节就问不出来了。比如有人简历里写了“使用组件化架构将项目拆分为20多个子模块”。我会追问这些模块是怎么划分的模块之间通信用什么方案主工程和模块之间怎么解耦如果候选人只能说出“用CocoaPods私有库”那基本就是了解过皮毛。真正做过组件化的人会提到路由、Protocol、Target-Action这些方案还会分析不同方案的优劣以及实践中踩过的坑。还有一种常见现象候选人简历写“精通性能优化”。我让他分析一个具体的卡顿场景比如TableView滚动时掉帧他会怎么排查。真正的性能优化经验应该包括用Instruments的Time Profiler定位耗时方法检查是否在cellForRowAt里做了耗时操作查看有没有离屏渲染有没有频繁创建对象导致内存抖动。能说出这套排查思路的才是真正做过优化的人。4. 跨平台混战uni-app、Flutter与原生iOS的正面交锋4.1 uni-app做微信小程序开发体验到底怎么样2020年之后微信小程序的业务需求爆发式增长。团队里既要维护iOS原生App又要做小程序人力严重不足。“一套代码多端运行”的跨平台方案就成了刚需。我们当时调研了uni-app、Taro、Flutter最终在部分项目里选了uni-app。客观地说uni-app在微信小程序端的开发体验是及格的尤其是对于Vue开发者上手成本极低。页面路由、组件化、Vuex/Pinia状态管理、uni.request网络请求这些能力都内置好了不用额外搭脚手架。但踩过坑也不少。最经典的坑是Canvas的异步问题。我处理过一个线上bug页面用uni-app的Canvas组件生成一张带二维码的海报图片在部分iOS机型上导出总是白图。排查了很久发现问题出在Canvas绘图操作是异步的每个绘图指令执行需要时间而uni.canvasToTempFilePath在绘图指令尚未执行完毕时就调用了导致导出的图片是空白。解决方案是等绘图操作完成后再导出比如用setTimeout延迟调用或者等图片加载完、文字绘制完的回调里再触发导出。这种异步时序问题在uni-app里特别常见尤其涉及Canvas、视频、音频这类重组件。另一个常见问题是iOS机型上网络请求失败率偏高。我们做过统计分析微信小程序在iOS端的网络请求稳定性确实不如Android尤其是弱网环境。后来通过web分析我们用的监控平台上报错误码6001表示网络异常发现大部分失败是超时和连接重置。解决思路是适当延长超时时间增加请求重试机制对关键请求做缓存降级。这里要特别提醒微信小程序的request请求iOS下默认并发限制比Android严格批量并发请求时更容易触发失败所以要注意请求调度避免一次性发起大量并发请求。4.2 微信小程序在iOS上的隐蔽坑静音播放与重复刷新微信小程序在iOS上有两个坑值得单独拿出来讲。第一个是静音模式下播放音乐。需求很简单用户把手机调到静音进入小程序后点一个按钮要能播放背景音乐。在Android上完全正常但在iOS上系统对音频播放有一个硬性规定——静音开关控制媒体声音。解决方法是使用InnerAudioContext它有一个obeyMuteSwitch属性。当设置为false时音频播放会忽略静音开关跟随物理按键的状态始终以媒体音量播放。但要注意这个属性只在部分iOS版本上生效兼容性需要实测。我们最终的做法是初始化音频上下文时把obeyMuteSwitch设为false同时兼容旧版本iOS在设置不生效时引导用户手动关闭静音模式。第二个坑是iOS微信H5和公众号页面的重复刷新问题。这个问题的表现是用户在iOS微信里打开H5页面页面的onload事件触发了两次导致埋点重复上报、接口重复请求。原因是iOS微信的WKWebView在特定场景下会重新加载页面比如从后台切回前台、用户拖动下拉时。解决方案可以是在页面加载时加一个session级别的标记如果短时间内重复初始化说明是重复刷新跳过第二次初始化逻辑或者在事件绑定前先解绑避免重复监听。4.3 Flutter与React Native见过猪跑也吃过猪肉我在不同阶段分别用Flutter和React Native做过外包项目的技术评估和原型开发。先说结论如果是纯新项目团队又有原生iOS基础Flutter的方案我会犹豫但RN我不会选了。React Native的问题是依赖桥接层原生模块的通信成本高而且每次React Native版本升级都可能导致第三方库不兼容。我在2018年帮朋友评估过一个RN项目的改造光适配React Native 0.57到0.59的升级就花了两周时间很多第三方库都停更了只能自己patch源码。Flutter相对好一些Dart语言的AOT编译让启动性能和运行性能都比RN好一截。自绘引擎让UI在各端渲染一致性极高不会出现同一个样式在iOS和Android上显示不同的情况。但Flutter的Dart语言生态还不够丰富一些冷门功能的第三方库质量参差不齐。而且Flutter包体积偏大对启动时间敏感的项目要慎重。对于大多数中小团队我的建议是如果核心场景是微信小程序优先uni-app因为小程序本身就是它的主战场如果有原生App业务老老实实维护原生项目如果是全新App、团队愿意学习新技术可以评估Flutter但要预留足够的技术调研时间。5. 那些年追过的热词背后都是真实需求5.1 iOS旧版软件库、延迟升级和自签普通用户的选择作为一个iOS开发者我经常被亲戚朋友问一些技术之外的问题旧手机能不能装老版本App、怎么延迟系统升级、证书怎么自签。这些需求虽然和开发无关但真实反映了普通用户对iOS生态的感受。iOS旧版软件库的核心问题是兼容性。苹果的App审核和系统升级机制逼迫开发者不断适配最新版本因而旧系统上能用的App越来越少。我记得iOS 9时代很多设备升到iOS 10、11之后老App还能勉强运行。但到了iOS 13之后64位App全面接管32位App被彻底淘汰大量的老App直接就打不开了。这个趋势之下旧版软件库网站确实有存在的价值但也要提醒下载来源不明的旧版App文件风险很高可能被植入恶意代码一定要谨慎。延迟升级是另一个刚需。苹果每年发新版iOS总有一部分用户担心新版本有bug、耗电增加、性能下降选择停留在旧版本。苹果官方其实提供了一个折中方案在系统设置里关闭自动更新然后手动删除已经下载的更新包。需要提醒的是苹果的签名验证机制决定了你没法永久停留在一个版本决定升级之前要做好心理准备。自签7天这个需求主要集中在游戏玩家群体。很多iOS用户想装非App Store的应用但苹果的免费开发者账号签名有效期只有7天过了就得重新签名。这个方案本身不复杂就是每次到期后需要连接电脑操作一次适合愿意折腾的用户。但从安全角度非官方渠道的应用风险自担这个必须说清楚。5.2 iOS自动化、分屏和系统镜像开发者眼里的新玩具iOS自动化在快捷指令App推出之后门槛大幅降低。我用快捷指令做过不少自动化场景每天早上自动播报天气和日程到了公司自动切换到工作模式晚上睡前自动开启勿扰模式。对于开发者来说快捷指令还支持URL Scheme和Webhook可以和自己的服务器打通实现更多玩法。iOS分屏功能从iPadOS 13开始逐步完善。很多用户不知道iPhone在横屏状态下部分App也支持分屏了但这个功能需要App主动适配。开发者做适配时要注意处理视图的大小变化事件避免界面挤压变形。我在做一款笔记App时专门适配过iPad分屏核心是处理好viewWillTransition和size classes不同宽度下布局要能自适应。Mac电脑安装iOS系统镜像这是一个很冷门但真实存在的需求。有人想在Mac上模拟iOS环境测试App有人想体验新系统的UI。苹果官方其实不提供iOS模拟器在非Xcode环境下的独立运行方式网上流传的各种“iOS镜像”基本都是非官方渠道包装的可靠性存疑还有安全风险。除非你有明确的技术测试需求否则不建议折腾。5.3 iOS黑客视角“无感”漏洞与安全测试的边界作为开发者我会关注一些安全领域的信息。SSLPinningSSL证书锁定是iOS App安全防护的重要手段它让App只信任特定的服务器证书防止中间人攻击。很多大厂App比如短视频平台、支付类App都用了这个机制。做安全测试时Charles抓包这种常规手段就失效了需要绕过证书校验才能看到明文数据。“iOS无感”这个热词背后是一种利用系统漏洞获取用户信息的技术手段。2015年我就见过类似的漏洞报告攻击者通过欺骗用户点击“允许”授权对话框在用户无感知的情况下完成权限授权进而获取敏感信息。苹果后来在系统更新中修复了这类漏洞但新的攻击方式不断涌现。研究这类漏洞是安全研究者的职责但普通用户能做的是尽量不越狱、不装来源不明的描述文件、不点击可疑的授权弹窗。还有那个看起来就很技术的词条stub for ios 18.7 — stage1 rce lives in rce_worker_18.7.js。RCE是远程代码执行的缩写Stage1 RCE通常指漏洞利用链的第一阶段一个JavaScript文件作为漏洞利用的入口配合iOS 18.7某个未修复的漏洞实现任意代码执行。这类信息多出现在安全研究圈子普通用户看看就好不必恐慌。作为开发者我们要做的就是把App的安全基础做好——代码混淆、越狱检测、防止调试器附加、敏感数据加密存储这些常规手段能大大增加攻击者的成本。6. 真金白银的踩坑记和一场实战复盘6.1 iOS Textarea输入框的遮挡逻辑“层盖”是怎么回事在uni-app和原生iOS开发里Textarea/UITextView的输入框遮挡问题是一个让人头大的经典bug。现象是用户在输入大量文字的时候键盘弹出来后输入框被键盘挡住了点击其他区域收键盘时整个页面又出现了奇怪的“层盖住按钮”的情况。我遇到的一个具体场景是一个反馈页面上有Textarea和提交按钮用户输入完文字后点击提交但按钮被一个半透明的层盖住怎么点都没反应。定位半天发现是Textarea在失去焦点时iOS会自动生成一个UITextView的快照视图这个快照在某些情况下会留在界面上盖住下方的控件。解决方案不复杂但需要从多个角度同时处理。第一在Textarea失去焦点时主动去调整scrollView的contentInset把键盘顶起的高度算清楚第二在失去焦点的回调里加上UIScrollView的setContentOffset动画让页面滚回顶部位置第三如果用了uni-app可以试试cover-view组件——但我实测下来cover-view和普通view的层级关系坑很多不如在页面onUnload或者点击提交时手动强制关闭键盘来得清爽。6.2 高版本备份恢复到低版本一场数据迁移的噩梦这个需求很特殊但确实存在用户手机升级到了iOS 17用了一段时间觉得新系统不好用想刷回iOS 16。问题来了iOS 17的备份数据默认格式和数据结构可能和iOS 16不匹配直接恢复会报错或者恢复之后出现各种奇怪的兼容问题。苹果官方是不支持从高版本备份往低版本恢复的这是系统层面的限制。网上能搜到一些“绕过方法”比如手动修改备份文件中的系统版本号、删掉某些记录文件再恢复。我出于好奇心测试过一次结论是风险和收益不成正比。修改备份文件可能导致短信、通讯录、照片等关键数据丢失而且操作过程极其繁琐。我的建议是真有降级需求先把重要数据手动导出然后做一个“干净”的降级——抹掉手机重新刷固件再从iCloud或手动方式恢复部分数据。6.3 图像处理中的一个隐坑iOS的图片压缩和方向问题iOS的UIImage有一个隐蔽的特性它自带imageOrientation属性相机拍出来的照片可能会带有方向信息。开发者在做上传功能时如果直接取UIImage的原始数据上传服务端收到的图片可能是旋转过的。这个问题在做图像上传、图像合成、Canvas导出时经常出现。我在做一个身份证识别上传功能时遇到这个坑。用户拍照上传身份证照片服务端识别率一直很低后来排查发现部分iOS设备拍出的照片带有EXIF方向信息上传时没有做方向矫正服务端拿到的图片是横着的识别自然失败。解决方案是重绘图片把方向信息固定为向上func normalizedImage(_ image: UIImage) - UIImage { if image.imageOrientation .up { return image } UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale) image.draw(in: CGRect(origin: .zero, size: image.size)) let normalized UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return normalized ?? image }这个坑在uni-app的Canvas导出场景同样存在导出图片前要先检查图片方向必要时先做旋转重绘再绘制到Canvas上。6.4 Safari下载文件变预览一个H5开发的顽固问题H5页面在iOS的Safari里下载文件经常会变成直接打开预览而不是触发下载。这其实是Safari对Content-Disposition响应头的一种处理策略。如果响应头设置成attachment; filenamexxx.pdfSafari通常能正确触发下载但如果服务端只返回了文件流没有加上Content-Disposition: attachment或者加的方式不对Safari就会直接尝试用内置预览器打开。解决方案是让服务端统一返回正确的下载响应头。对于无法修改服务端的场景前端可以用blob加a标签的方式强制下载fetch(url, { method: GET }) .then(res res.blob()) .then(blob { const link document.createElement(a) link.href URL.createObjectURL(blob) link.download filename.pdf link.click() URL.revokeObjectURL(link.href) })要注意iOS Safari对a标签的download属性支持并不完美某些场景下还是会走预览逻辑。更可靠的方式是使用navigator.share让用户选择保存位置但这个方案的体验和兼容性也一般。最终我们采用的方案是后端配合返回正确的引用头前端再做一个兜底——检测到Safari内打开文件时提示用户长按文件链接选择“下载链接”这算是最不优雅但最保证能用的办法。7. 给新人的建议这十年我踩过的坑你最好别踩7.1 基础永远值得花时间别上来就追框架很多新人上来就盯着最新的SwiftUI、最新的Composable Architecture结果基础不牢写出来的代码一团糟。我的建议是先花时间把UIKit、Auto Layout、GCD、内存管理这些基础彻底吃透再去碰框架。框架是解决特定问题的基础是解决一切问题的。面试的时候基础好的候选人即使没接触过某个框架聊几句就能举一反三基础差的简历写满新技术栈一问细节就露怯。我见过太多人Objective-C语法都还没弄明白就想着学SwiftUIUIViewController的生命周期都说不清就开始研究协程。这种学习路径看起来很“快”但经不起推敲。真正的成长是慢功夫你花一个星期研究内存管理的细节可能在半年后的某次排查线上崩溃时直接帮你省下一天时间。7.2 遇到奇怪bug先别怀疑是系统问题做iOS开发遇到诡异的bug最容易犯的错就是把问题归咎于“系统bug”。诚然iOS确实存在一些系统层面的问题但绝大多数情况下问题出在你自己写的代码上。我处理过最匪夷所思的一个bug一个页面在特定机型上滑动时卡顿排查了半天最后发现问题是一个图片加载库在后台线程更新了UI导致主线程被频繁唤醒。正确做法是遇到问题先复现能稳定复现的问题用排除法逐步缩小范围不能稳定复现的问题先埋点收集足够多的日志再分析。工具方面Instruments是永远的利器Time Profiler分析卡顿Leaks分析内存泄漏Activity Monitor分析CPU占用。还有就是老生常谈崩溃日志一定要好好利用symbolicatecrash拿到崩溃堆栈能定位到具体哪一行代码崩溃比你自己瞎猜强一百倍。7.3 善用Charles抓包理解底层协议才是硬道理Charles是iOS开发者的老朋友。装好证书、设置好代理之后你就能看到App的所有网络请求。大多数开发者用它来看接口数据、调试联调但真正的高手会用Charles做更多事情断点修改请求和响应、模拟慢网、重复请求、修改网络状态。我记得有一次联调后端接口还没准备好我用Charles的Rewrite功能把接口的请求URL重新指向本地Mock服务再用Breakpoint功能拦截响应模拟各种极端情况的数据。前端开发和后端开发完全解耦效率提升了不止一倍。但抓包也有失效的时候就是前面提到的SSLPinning。针对这种情况有经验的安全团队会在App里加一个调试开关只在Debug模式下禁用证书校验方便开发联调。这个方案比直接关闭SSLPinning安全得多也便利得多。8. 面向2025年iOS开发者该往哪里走8.1 从iOS到全平台一个不好回避的话题2025年iOS开发已经不再只是“iOS”这一个平台的事情了。苹果生态已经覆盖了iPhone、iPad、Mac、Apple Watch、Apple TV、Vision Pro而“一次编写、到处运行”的SwiftUI和Swift让通用化开发成为可能。一个用SwiftUI开发的App可以同时跑在iPhone和Mac上这是以前想都不敢想的事。但全平台开发也意味着更多挑战。不同平台有不同的交互习惯和系统特性不能简单套用一套UI。举个例子iPad上需要更好的键盘操作支持Mac上需要菜单命令Apple Watch上界面尺寸极小这些都需要单独适配。我在开发一款笔记App时最初只考虑了iPhone端后来加了iPad和Mac支持每个平台都花了不少时间去调试布局和交互细节。但做完之后的收益也实实在在用户群大了口碑也好了。8.2 模块化、CI/CD与质量保障的成熟基建十年前做iOS开发打包发布全靠手动Xcode编一个包传到TestFlight再发邮件让测试人员安装。到了2025年成熟团队基本都有完整的CI/CD流水线了。GitLab CI、Jenkins、GitHub Actions都能跑iOS构建核心是用xcodebuild和xcodebuild test这两个命令行工具。我的建议是团队至少要有三条流水线PR合并后自动跑单元测试和UI测试每日凌晨打一个 nightly 包供测试人员使用打正式tag时发布App Store构建。另外fastlane这个工具链一定要学它封装了证书管理、打包、上传、发布的一整套流程配合Match做证书的集中管理能省掉大量重复劳动。质量保障方面除了常规的单元测试和UI测试崩溃监控和性能监控是必备的。我们用的是Bugly数据上报也会有好多问题需要排查但总归能让你在用户吐槽之前发现大多数问题。再配合审计日志埋点系统每个关键操作都有迹可循排查线上问题时能省很多时间。8.3 AI与AI编程助手对iOS开发的真实影响最后聊一下AI。2023年以来AI编程助手已经成了我日常开发的一部分。说实话目前AI还不能完全替代开发者但它的价值已经非常明显了写单元测试、生成重复性的UI代码、解析崩溃日志、解释老代码逻辑这些事AI干得又快又好。比如我接手一个老项目时面对几千行看不懂的业务代码直接丢给AI去解释很快就能梳理出大致模块和数据流。再比如写一些模板化的网络请求层、Model层的代码AI生成的代码基本可以直接用。遇到报错把错误信息贴给AI很多时候它能直接给出解决方案。但AI也有不靠谱的时候。生成代码时偶尔会有隐藏bug尤其是涉及线程安全和内存管理的场景。所以我的原则是AI生成的代码必须自己读一遍理解每一行在干什么再做代码评审。AI是效率工具不是替你思考的工具这个定位要清楚。9. 写在最后十年iOS开发的一些真心话从2015年到2025年iOS开发这个领域的变化用“天翻地覆”来形容一点也不夸张。语言从Objective-C切换到Swift又从Swift 1迭代到了Swift 6UI从UIKit演进到SwiftUI架构从MVC到MVVM再到Composable Architecture工具链从Xcode独占到现在CI/CD一体化。但有一点始终没变这个领域永远缺不了真正热爱技术、愿意深挖细节的开发者。我自己这十年最大的体会是做好iOS开发最重要的不是掌握多少框架而是具备扎实的计算机基础、严谨的逻辑思维和持续学习的能力。遇到问题不慌张先定位再解决写代码多思考一步想想会不会有内存问题、线程问题、兼容性问题做架构设计时多考虑一步想想未来半年、一年这个项目会怎么发展。如果你刚入行或者正在路上我给你三个实在的建议。第一把基础打牢Objective-C可以不用精通但Swift和核心框架一定要扎实第二多动手做完整项目面试聊起来时一个完整的项目经验比十个Demo有价值得多第三保持好奇心iOS生态每年都在变养成读苹果文档和WWDC Session的习惯你会发现很多困扰自己很久的问题其实官方早就给出了标准答案。最后送给大家一句我很喜欢的话“代码是给人看的顺便给机器执行。”十年iOS开发到头来我更在意代码的可读性和可维护性毕竟任何一个项目都不是一个人的战斗。希望你的iOS开发之路也能走得比我更稳、更远。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。