我是Ioser 铭从2015年正式入行iOS开发到今年正好第十个年头。这十年里身边一起写代码的人换了一茬又一茬有人转去后端搞高并发有人转行为产品经理还有人直接离开了互联网行业。我倒是挺执着一直蹲在iOS开发这条路上没挪窝。回想起来这十年的主线其实无非两件事跟着系统版本跑跟着架构设计跑。每次系统一升级新一轮适配、重构、踩坑就开始了每次架构思潮一变现有的代码就得琢磨怎么拆、怎么改、怎么重构。这篇文章不打算按年份写流水账而是想把这十年的iOS开发经验浓缩成几个真正值得聊的话题语言演进、架构变迁、跨端对比、工程化建设以及中途踩过的大坑。里面有不少经验是用加班和故障换来的希望能让刚入行的新朋友少走弯路也能让正在做技术选型的老朋友看得过瘾。1. 十年语言栈变迁从Objective-C到Swift再到SwiftUI1.1 2015年入行时手写Objective-C的年代2015年入行那会儿Swift刚发布一年网上天天有“Swift会不会取代Objective-C”的争论但绝大多数商业项目还在老老实实用Objective-C。我入职第一天的任务就是读完公司项目的两个核心类印象很深——一个文件一千多行各种addTarget绑定、代理回调、通知监听混合着写看了一个下午头都是大的。那时候写界面主要靠纯代码加Masonry或者直接用XIB。占位图用UIImageView加contentMode列表用UITableView配UITableViewController。当时的iOS开发有个特点一份代码要同时适配iPhone 4s和iPhone 6 Plus屏幕从320pt到414pt跨度巨大Auto Layout又刚普及不久很多老同事习惯手动算frame。被折磨多了自然就开始看各种开源库。AFNetworking做网络请求SDWebImage做图片缓存MJRefresh做下拉刷新YYModel做字典转模型——这些第三方库几乎是每个工程的标配。但Objective-C的语法确实啰嗦[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cell]这样的写法现在回头看会觉得很遥远可当时每天都在写。对新手来说现在不必刻意去学Objective-C了但如果你要维护老项目至少得读得懂它的头文件、属性修饰符和消息发送语法。老项目里大量的property (nonatomic, strong)、synthesize、block回调是理解内存管理的活教材。1.2 Swift混编期一场持续三年的阵痛2016年到2018年Swift迎来了剧变Swift 2.x、3.0、4.0一路狂奔API设计规范改了又改。Swift 3最大的一次变动是把所有方法名的第一个参数标签强制保留导致大量第三方库API彻底变化。公司项目从Objective-C迁移到Swift的过程就是一场持续了快两年的战斗。混编期最大的问题是两套语言之间的桥接。Swift调用Objective-C类需要在桥接头文件里导入Objective-C调用Swift类则需要Xcode自动生成的-Swift.h头文件。这中间一旦出现命名冲突、类型转换、泛型擦除问题编译报错的信息又很难看懂常常一个错误卡一下午。那个阶段我还踩过一个经典坑Objective-C里返回NSError **的方法桥接到Swift里变成throws但反过来Swift里抛出错误给Objective-C调用方时错误类型会被擦除为NSError。如果你在跨语言时希望保留具体的错误code必须手动处理。类似的边界情况在官方文档里写得很含糊只能靠一点一点试出来。到了Swift 5ABI终于稳定了才算是真正能安心使用的版本。但我个人的体感是Swift 4到Swift 5之间是很多团队技术选型的分水岭。因为混编成本高、编译速度慢许多老牌App一直坚持到2021年才开始大规模用Swift重写。1.3 SwiftUI与并发框架2020年后的新范式2020年iOS 14发布SwiftUI终于从“玩具升级为生产力工具”。声明式UI和Combine响应式框架对习惯UIKit命令式写法的老iOS开发者来说是一次思维方式上的重启。原来的viewDidLoad、layoutSubviews、tableView:cellForRowAtIndexPath:都被拆解成了State、Binding、ObservableObject界面不再是“被代码一步步画出来”而是“由数据状态驱动自动计算出来”。刚开始写SwiftUI非常不适应一个List里嵌套Section、ForEach感觉跟写前端模板似的。但真正玩明白之后SwiftUI的开发效率确实比UIKit高太多了尤其是复杂列表和多级页面跳转代码量能少一半。配合MainActor、Task和async/await网络请求和数据刷新的代码也变得异常简洁。不过SwiftUI也有自己的问题它对iOS 15以下版本的新API支持不佳很多属性只能用if #available包裹时间长了代码会变得很脏。另外预览机制在复杂项目中很不稳定经常需要重启Xcode才能恢复。2. 架构演进从MVC到MVVM再到模块化2.1 最初的MVC为什么Controller越来越胖回到老项目的话题上。2015年的iOS工程几乎全是MVC架构Model层放数据模型View层放UI控件Controller层负责几乎所有逻辑。初期代码量小MVC相当好用一旦业务复杂起来Controller就变得越来越胖一万多行的ViewController并不是什么稀奇事。我还记得接手过一个电商项目的订单列表页Controller里面同时堆了网络请求、数据解析、空态判断、下拉刷新、点击跳转、统计埋点、分享回调光是这个文件的代码就跑了快三千行。每次需求改动所有人都要小心翼翼地在同一片方法区里找位置代码冲突简直是家常便饭。后来我们决定把网络请求和数据解析抽出去单独成OrderService和OrderModelParserController瘦身了但业务状态的管理依旧很成问题。MVVM的出现正是为了解决这个问题ViewModel层专门负责把数据加工成视图需要的状态Controller只负责绑定和转发。但当时的iOS社区没有内置的绑定机制大家只能借助ReactiveCocoaRAC或者KVO而RAC的学习曲线又极其陡峭——我记得自己读了整整一周的RAC文档才终于搞懂什么是“信号”什么是“订阅者”。2.2 MVVM的成熟响应式编程与轻量绑定2018年之后MVVM在iOS圈逐渐成为主流。RAC用起来太重大家开始自己封装轻量绑定工具或者拥抱CombineiOS 13。这个阶段的项目结构通常是View层持有ViewModelViewModel持有业务数据View通过didSet观察数据变化刷新UI。我比较推荐的中小型项目做法是不引入重型第三方框架而是用Swift的ObservableObjectPublished做数据绑定iOS 13以上。如果团队还兼顾旧版本就自己写一个简单的BoxT类用onValueChanged闭包当作迷你绑定器。这样既不需要学习额外框架又能在ViewModel层统一做状态管理。MVVM最关键的收益不是代码行数变少而是职责边界清晰了。ViewController只负责布局和转场ViewModel只负责业务逻辑和状态Model只负责数据。这样一来单元测试也变得容易多了——测ViewModel的逻辑完全不需要搭UI环境跑起来飞快。2.3 模块化与TCAiOS大型项目的新解法业务规模继续膨胀后MVVM也扛不住了。一个App里有几十上百个页面如果所有ViewModel都塞进同一个Target编译时间轻松突破十分钟。于是模块化架构开始流行按照业务域拆分成多个Framework再通过CocoaPods或Swift Package Manager管理依赖。做模块化需要提前规划好依赖关系图依赖方向只能从上向下不能有环形依赖。当时我们团队把项目拆成了基础层网络、存储、UI组件、中间层业务模块、顶层App壳三层结构编译速度明显提升团队协作也顺畅了——各个小组只需要关注自己负责的模块公共组件改动时只要保证接口兼容就不会牵一发动全身。最近两年Composable ArchitectureTCA开始受到关注。TCA借鉴了Redux单向数据流的思想State变化触发ReducerReducer返回EffectEffect再派发Action。这种架构的好处是极度统一所有业务逻辑在Reducer里集中处理特别适合复杂流程和多人协作。但缺点是样板代码多、学习成本高不太适合中小型项目。我的建议是团队人数不多、业务不复杂MVVM就够了如果模块之间交互复杂、状态流转频繁再考虑引入单向数据流架构。3. iOS开发与移动端生态uni-app、微信小程序、Android与鸿蒙的一次横向比较3.1 iOS生态的独特价值为什么还是有人选择原生做iOS开发十年总会被问到同一个问题现在跨端框架这么多为什么还要学iOS原生我的回答一直是iOS生态依然是移动开发里最讲求体验和品质的阵地。iPhone和iPad的设备型号相对有限系统版本更新也比较统一开发者在适配上的压力比Android小不少。再加上Apple对App Store的审核有一套明确规范包体大小、隐私权限、支付流程都有要求App的底子相对干净。对用户来说iOS触控的跟手度、SwiftUI的手势动画、Metal渲染的流畅度都是体验上的加分项。原生开发在性能上始终是天花板跨端方案很难追平。此外iOS的私域生态非常成熟HealthKit、CoreBluetooth、ARKit、CoreML、WidgetKit、ShareExtension这些能力都要靠原生API调用。如果核心业务强依赖这些能力跨端方案很难替代原生今天的在线教育、运动健康、AR购物基本都是原生开发为主。3.2 uni-app开发微信小程序Vue语法带来的跨端便利uni-app是我经常向公司推荐的一种非原生方案。它使用Vue语法一套代码可以同时编译到微信小程序、App、H5等平台。实际落地之后它的优势非常明显前端团队可以零成本切入只要会Vue基本不用额外学太多移动端知识就能开发小程序和App。比如在微信小程序里写一个登录页页面结构、样式、逻辑都是Vue SFC的写法编译工具会把它转成小程序的WXML/WXSS。uni-app对Vue生态的兼容也算到位vuex、vue-router都能直接使用。不过跨端方案也有天然的短板。最突出的是性能问题uni-app在App端需要带一个运行时桥接层性能比原生差一些在小程序端代码包经过编译后会增大体积逻辑层和渲染层每次通信都有耗时遇到长列表或者高频交互会明显卡顿。另外当需要使用微信支付、小程序登录、地图等原生能力时uni-app虽然提供了统一API但内部的适配逻辑是封装好的一旦遇到边界情况很难深入排查问题。我的建议是如果业务主要面向微信生态且要求快速上线可以选uni-app如果核心体验要求极高或者要深度使用硬件能力还是优先原生。3.3 iOS、Android与鸿蒙的技术栈对比这三者的对比其实本质是开发语言和框架思维的对比。iOS开发Swift UIKit/SwiftUI Xcode工具链封闭但高度集成。优点是好用、规范缺点是只能跑在Apple平台上。Android开发Kotlin Jetpack Compose Android Studio与iOS的SwiftUI在UI构建上理念很像。Android真机碎片化严重厂商ROM各搞一套权限管理、后台进程、杀后台策略千奇百怪适配工作量比iOS多不少。鸿蒙开发ArkTS ArkUI DevEco Studio语法上很像TypeScript SwiftUI的结合体。它的设计目标是要做到一次开发、跨多端部署手机、平板、车机、电视等。鸿蒙近两年的增长速度确实快从项目数量看越来越多的公司开始要求储备鸿蒙开发的技能。但鸿蒙生态还在成长期三方SDK、开源库和成熟组件相对有限很多功能需要自己造轮子。这三条线如果要选我的思路是iOS原生和Android原生的能力积累是通用的至少要懂其中一门否则很难理解跨端框架的底层逻辑。鸿蒙方向可以作为增值技能但现阶段不需要盲目投入全部精力。3.4 微信小程序的独立生态前端逻辑与原生体验的折中微信小程序和传统App有个本质区别它不需要安装、天然拥有微信的社交传播能力。但小程序的运行环境是WebView 原生组件混合的有核心的双线程模型逻辑层跑在JavaScriptCore里渲染层由WebView完成两者通过setData通信。这也就解释了为什么小程序里做复杂计算会卡因为逻辑层和渲染层之间每一次数据传递都有成本。2020年后微信又推出了Skyline渲染引擎支持同层渲染让小程序动画和滚动体验更接近原生。但实际开发中小程序工程依然要对setData内容做极致的精简只把变化的数据传过去避免频繁触发整个页面重渲染。如果你的产品既需要App又需要小程序最省事的路径是核心业务做成uni-app或Taro一套Vue/React代码输出两端但涉及支付、扫码、蓝牙等系统能力时要有心理准备去处理平台差异、写条件编译。4. 工程化与质量保障签名、CI、崩溃与性能优化4.1 代码签名与证书管理为什么它总在“关键时刻出问题”iOS开发里最绕不过去的基础设施就是代码签名。每个iOS应用在真机安装或上架前都必须进行签名签名用的证书和描述文件掌握在开发者账号里。项目开发到一半最常见的翻车就是证书过期、描述文件与Bundle ID不匹配、开发设备没加入设备列表。这些问题的核心逻辑在于签名是一套“信任链”Apple通过证书链验证代码确实来自注册的开发者描述文件则限定了这个包能在哪些设备上跑、能使用哪些能力。遇到签名报错我通常的做法是先跑一次security find-identity -v -p codesigning检查本机证书再到开发者后台检查描述文件最后在Xcode Build Settings里检查CODE_SIGN_IDENTITY和PROVISIONING_PROFILE是否对应的上。强烈建议团队用fastlane match来管理证书和描述文件它会把私钥加密放进仓库团队成员拉取后自动安装配置能有效避免证书混乱。如果一个项目组经历过证书被同事误删、描述文件过期、两台电脑签名不一致的问题就会理解这有多重要。4.2 CI/CD自动化从手动打包到一键发布早期我们在项目里打包全靠开发者手点Xcode。每次发版都要重复以下步骤改版本号、改构建号、Archive、导出ipa、上传到TestFlight或App Store Connect。这中间只要有一次操作失误比如选错Export Method、漏掉描述文件就要重新打包非常浪费时间。后来我们上了fastlane Jenkins的自动化流水线。开发者只需要在提交代码时打上特定tagCI就会自动拉代码、跑单元测试、打包、上传蒲公英或TestFlight再通过消息通知群里所有人。这一步做完整个团队的发版效率至少提升了一倍。CI的配置有几个关键点一是必须使用独立签名不要在CI机器上手工导入证书二是要配置好Keychain的密码否则codesign会卡住等待用户输入三是产物清理要做好磁盘空间很快会被积压的ipa撑满。对于小团队用GitHub Actions或者GitLab CI也是一种轻量替代不一定非得自建Jenkins。4.3 崩溃治理与性能优化iOS开发的高阶必修课产品上线后最怕的是两件事崩溃和卡顿。崩溃治理的第一步是接入崩溃监控SDK比如Firebase Crashlytics或自研上报平台然后每天盯符号表是否上传完整——符号表一旦缺失崩溃日志里的堆栈全是内存地址基本上没法排查。我处理过一个非常隐蔽的崩溃一个数组在子线程被同时读取和写入崩溃堆栈每次都指向不同的系统库方法。后来用Address Sanitizer复现才发现是数据竞争。解决方式也简单所有对那个数组的访问都放到主线程或者用锁保护起来。类似这种问题排查看的不是运气而是对并发模型的理解深度。性能优化方面启动时间是第一优先级。App冷启动时长直接决定用户留存。优化思路一般是减少动态库依赖、避免启动时加载大文件、把非关键任务放到异步线程、用load方法的操作尽量后移。iOS 15之后Xcode自带MetricKit可以自动采集启动时间、卡顿率等数据省去了自己埋点的工作。包体体积优化同样值得投入。App Store对蜂窝网络下载有150MB的硬限制超了就只能连WiFi这会极大影响转化率。常见的瘦身方案包括移除无用架构armv7、x86_64、压缩资源图片、App Thinning、按需加载资源。在一个大型项目里通过这些手段把包体从180MB降到130MB并不是什么难事。4.4 App Store审核避坑笔记跟App Store审核打了十年交道我的总结是审核不是玄学而是规则理解的问题。Apple的审查准则写得清清楚楚但很多开发者不看原文只靠道听途说结果被拒之后还不知道为什么。常见的被拒原因包括缺乏隐私政策Guideline 5.1.1、使用私有APIGuideline 2.5.1、包含隐藏功能Guideline 2.3.1、订阅支付没有走IAPGuideline 3.1.1。其中IAP是红线中的红线千万别试图绕过一旦被发现轻则下架重则封号。另一个容易被忽视的坑是IDFA。如果你的App接入广告SDK或做归因在申请“追踪用户”权限时必须在Info.plist里配置NSUserTrackingUsageDescription且描述要清晰。如果用户拒绝授权代码里也要做好降级逻辑不能崩溃。被拒后不要慌先在App Store Connect后台查看“App Review”的完整反馈里面通常有截图或录屏。能解决的改完重新提交解决不了的就写清楚原因。这里有一个经验回复审核团队的留言要语气友好、描述具体几轮对话就能解决的事千万不要跟审核员杠。5. 十年iOS开发踩坑实录实操中容易翻车的细节5.1 内存管理与引用循环iOS开发最经典的坑就是引用循环。delegate用strong修饰、block里强引用self、子线程持有大对象这些都会导致内存无法释放。调试方法很简单用Xcode的Memory Graph跳转后能看到对象间的引用链。我印象最深的是用CADisplayLink做动画时闭包里引用self而self又持有这个CADisplayLink页面退出后动画一直不停内存占用只增不减。修复也简单最终在deinit里invalidate定时器或者在闭包里用[weak self]捕获列表。5.2 线程安全看似安全的DispatchQueue实则处处是雷并发编程是iOS开发里的高危地带。异步操作回主线程刷新UI是最基本的要求但很多人漏掉了“主线程检查”——在viewDidLoad里调一个异步函数等数据回来时页面可能已经Pop了如果不判断self是否还存在就会崩溃。线程安全的核心是“加锁”和“隔离”。复杂并发场景下尽量把数据操作串行化比如用DispatchQueue(label: com.xxx.serial)或者在Swift 5.5后用actor隔离状态变更。使用actor后编译器会在跨actor调用时强制你await这比纯靠自觉安全得多。5.3 自适应布局与多机型适配屏幕适配从2015年的3.5英寸iPhone 4s到现在各种刘海屏、灵动岛布局使用Auto Layout是主流但SafeArea、topAnchor、bottomAnchor的兼容逻辑容易出错。适配时我一般会跑一遍全面屏尺寸判断比如用UIDevice.current.userInterfaceIdiom区分iPad和iPhone用UIScreen.main.bounds判断尺寸范围再用UIStackView和约束优先级处理不同屏幕下的弹性布局。SwiftUI的适配思路与UIKit不同它更强调GeometryReader和ViewThatFits但核心思想是一致的不要到处写死frame(width:height:)要充分利用约束、优先级和内容压缩阻力去撑起UI。5.4 版本迭代与API弃用系统的每个大版本都会废弃一批API。从iOS 13开始的UIApplication.shared.statusBarFrame废弃到iOS 15的UIAlertView彻底移除再到iOS 16之后Push通知的回调变化每一年都会因为API弃用引发一堆编译警告或运行异常。好的习惯是在每个新系统beta版发布后花半天时间跑一遍全项目检索已知的deprecation警告提前修复踩坑点。xcodebuild也支持带-analyze静态分析可以帮助发现潜在内存问题与线程问题。写在最后十年iOS开发的一点个人体会如果现在让我对刚入行的iOS开发者说一句话我会说不要焦虑技术迭代快核心思路永远是底层那几件事——数据流、状态管理、并发与内存。从MVC到MVVM再到TCA底层思考从来没变过从Objective-C到Swift再到SwiftUI也只是语言的表象在变。这十年里我见过很多长期写UI而忽略网络层原理的开发同学一到排查问题就束手无策也见过很多连模拟器都还没跑顺就急着追新框架的小伙子。真正的成长路径应该是先把iOS系统的运行机制摸透再用具体项目去验证最后在踩坑中不断修正认知。就拿最近两年流行的跨端方案来说uni-app、鸿蒙这些新方向确实很热但不代表原生开发就失去了价值。底层能力和平台理解才是吃饭的本事就算你以后转去做跨端、做小程序、做鸿蒙iOS开发的经验依然能帮你少走很多弯路。如果这篇总结能给你的技术栈选择带来一点参考那就值了。
企业数字化 ERP 产品动态
相关推荐
AXI Crossbar设计详解:从协议机制到验证调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:20:46
不只是PD诱骗:CH32X035这颗RISC-V通用MCU的隐藏技能 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:20:46
提前和单位沟通,争取业绩与获奖机会 好的,作为一名在广西职称评审领域深耕多年的观察者,我经常听到这样的困惑:“我业绩不比别人差,为什么评职称总是轮不到我?”今天,我们就通过几个真实的对话场景,来聊聊这个关键问题——提前和单… · 2026/9/24 13:20:40
Instant Storage 文件上传与托管实战指南:从图片网格到权限控制 后端数据库 【免费下载链接】instant Instant is the best backend for AI-coded apps. You get auth, permissions, storage, presence, and streams — everything you need to ship apps your users will love. 项目地址: https://gitcode.com/gh_mirrors/inst/i… · 2026/9/24 15:33:35
Skia 正确性测试工具 DM 完整指南:从构建、运行到回归比对 图形学 【免费下载链接】skia Skia is a complete 2D graphic library for drawing Text, Geometries, and Images. See documentation for contribution instructions. 项目地址: https://gitcode.com/gh_mirrors/ski/skia 点击查看 免费下载 Skia 的官方文档 Cor… · 2026/9/24 15:33:35
cuDF 贡献指南:从环境搭建、源码构建到调试与代码规范的全流程实战 数据分析数据工程机器学习 【免费下载链接】cudf cuDF - GPU DataFrame Library 项目地址: https://gitcode.com/gh_mirrors/cu/cudf 点击查看 免费下载 导读
cuDF 是 RAPIDS 生态中的 GPU DataFrame 库,包含 C(libcudf)、Pyth… · 2026/9/24 15:33:35
chat4cj群组管理实战:一文精通群组创建、所有者轮转与归档操作 chat4cj群组管理实战:一文精通群组创建、所有者轮转与归档操作 【免费下载链接】chat4cj Rocket.Chat Cangjie 语言客户端 项目地址: https://gitcode.com/Cangjie-TPC/chat4cj
chat4cj(Chat RestAPI) 是一个用 Cangjie 语言编写的 Ro… · 2026/9/24 15:33:28
大麦自动抢票 3 分钟跑通:Selenium + Appium 双端配置到开票时刻 大麦自动抢票 3 分钟跑通:Selenium Appium 双端配置到开票时刻 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase
开票前 3 分钟ÿ… · 2026/9/24 15:33:28
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44