ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

十年iOS开发实战复盘:从Objective-C到Swift与跨平台演进

十年iOS开发实战复盘:从Objective-C到Swift与跨平台演进 我是铭一名做了十年 iOS 开发的工程师。2015 年入行时Objective-C 还是绝对主流Xcode 停在 6.4App Store 里的大厂应用清一色用 Masonry 写约束谁要是说自己用 Swift多半会被当成激进分子。十年下来我上线的应用超过二十个从纯原生一路写到了 uniapp、微信小程序甚至和鸿蒙团队坐在一起聊过技术方案。今天把这段经历完整复盘一遍其中大部分是踩坑之后才沉淀下来的东西希望能给同行和想入行的新人一点参考。1. 十年刻度2015 年的新手村长什么样1.1 那年的技术栈与开发环境2015 年的 iOS 开发和今天完全是两个物种。那时候 Xcode 6.4 刚支持 Swift 1.2但绝大多数商业项目依然用 Objective-C 开发。我刚入职第一家公司时技术负责人更是直接定了规矩主语言用 OC界面层用 storyboard 加 xib网络层用 AFNetworking图片加载用 SDWebImage数据库用 FMDB约束布局全走 Masonry。这套组合在 2015 年前后几乎就是国内 iOS 开发的标配CocoaPods 也已经成为主流依赖管理工具但你还必须手工配置 Podfile 里的 source 地址遇到公司内网发布私有库时pod install 失败是家常便饭。那个年代最折磨人的几件事现在的新人可能都想象不到。第一是签名证书频繁失效开发者账号里加一台新的测试机就要重新生成 provisioning profile有时候改了 bundle id 却忘了更新授权文件App 在真机上秒闪退。第二是崩溃日志抓取困难没有像样的崩溃平台全靠自己做异常捕获把 NSException 的调用栈写到沙盒里再手动上传。第三是屏幕适配2015 年正是 iPhone 6 和 6 Plus 普及的时候App 必须同时适配 4 寸、4.7 寸和 5.5 寸屏幕代码里到处是宏定义判断屏幕宽度写起来相当痛苦。这套组合拳我整整打了一年才慢慢理解其中的设计逻辑OC 的动态特性配合 Runtime 能做很多灵活的事Masonry 用链式语法简化了 AutoLayout 的冗长FMDB 则让复杂的本地数据查询变得可控。说到底2015 年的技术栈虽然原始但它把 iOS 开发里最核心的内存管理、布局系统和网络模型都逼着你学会了一遍这些底子直到今天依然有用。1.2 第一个从 0 到 1 的项目复盘我参与的第一个完整项目是一个电商类 App要求兼容 iOS 8 及以上一个月上线。当时我心里完全没底光是“兼容 iOS 8”这一条就够呛。那年 iOS 9 刚发布很多用户还停在 iOS 8两个系统在 UIAlertController 的 API 上有差异在状态栏样式的处理上也不一致稍不注意就会写出只在真机上崩溃的代码。为了保证进度我们采用了一张 storyboard 作为主导航骨架所有列表页和详情页用 xib页面内部用 Masonry 做自适应约束。这个项目给我留下最深的教训是关于技术债务。为了赶上线我们把大量逻辑塞进控制器一个 ViewController 动辄一千多行业务判断全部用 if-else 堆网络请求回调层层嵌套。上线那周确实欢天喜地但接下来的三个月每天都在还债改一个 UI 文案要顺着控制器翻半天加一个新的商品类型要动底层数据模型修 A 问题常常带出 B 问题。更惨的是产品经理随后要求加购物车批量结算这功能如果要做得稳必须重构订单模块但当时业务不能停我们只能继续在原架构上缝缝补补导致整个迭代周期越拉越长。现在我带团队时第一件事就是强调模块边界和代码结构。功能再急也不能把网层和业务层全部耦合在一起。2015 年那个项目让我明白一个道理iOS 开发不仅仅是把界面做出来、把接口调通更关键的是在快速迭代里保持代码的可维护性。这个认知是我入行第一年最大的收获。2. 技术栈演进从 Objective-C 到 Swift再到系统生态织网2.1 Objective-C 时代的三大必修课如果你是从 2015 年走过来的 iOS 开发者应该对下面这三样东西再熟悉不过它们决定了一个 OC 工程师的段位。第一是内存管理思维。ARC 在 2015 年已普及但 ARC 并不是帮你把内存问题全解决了它只接管了“引用计数”这部分。开发者仍然需要搞清楚 strong、weak、copy、assign 的区别以及 block 和 delegate 的持有关系。最常见的崩溃是控制器 A 强持有网络请求对象网络请求的 completion block 里又强引用 A形成循环引 用导致 A 永远不能释放或者用 NSTimer 时不手动 invalidate定时器一直持有 target页面退出也不走 dealloc。这种问题在 Instruments 的 Leaks 里一眼就能看出来但新手往往连 Instruments 都不太会用。第二是 Runtime 的日常应用。OC 的 Runtime 能把方法调用转发、动态添加方法、关联对象、Method Swizzling 这些高级玩法变成生产力。比如埋点 SDK 想在所有 UIViewController 的 viewWillAppear 里自动上报页面名称最简单的方式就是通过 Runtime 交换方法实现。关联对象更是在 category 里添加属性时的必备手段。但要小心Method Swizzling 一旦在 load 方法里做且没有使用 dispatch_once并发环境下就可能产生不可预料的坏味道我见过线上 App 因为这个在启动阶段偶发崩溃查了两天才定位到。第三是 Category 和继承的选择。2015 年左右很多人喜欢用 category 给 UIKit 组件加便捷方法例如 UIColor 的分类、UIView 的分类这确实能提升开发效率但如果 category 里随意覆盖了系统方法顺序不稳定或者和别人的 category 冲突问题就会很隐蔽。我的习惯是凡是可能被外部重用的能力优先写成独立的工具类category 只做轻量封装。2.2 Swift 迁移与混编实战Swift 从 2014 年发布到我真正在商业项目里大规模使用中间隔了将近三年。2016 年 Swift 3 刚出来时API 命名变化非常大a.b.c( ) 这种写法换来换去社区里最流行的一句话是“Swift 一年一换谁能跟得上”。真正让我下决心切 Swift 是在 Swift 4 之后那时 ABI 稳定看起来有希望代码提示比 OC 舒服太多泛型和协议扩展也让代码结构更清晰。但我们公司没有底气做全面重写只能走 Swift 和 OC 混编的路子。混编的第一个坑是桥接头文件。Swift 调用 OC 需要生成 xxx-Bridging-Header.hOC 调用 Swift 则需要在 target 里开启“Always Embed Swift Standard Libraries”但当时这个配置在部分诡异路径下会漏掉动态库导致真机安装后启动崩 溃。混编的第二个坑是命名冲突OC 的分类方法和 Swift 的扩展方法很容易“撞车”编译器报错又不够直观有时你得先在 Build Settings 里打开“模块编译”才能看到具体冲突位置。第三个坑是 OC 的 generics 和 Swift 的泛型桥接不完全OC 数组里存 NSString桥接过来可能变成 Any业务层必须反复做类型判断。这套混编经验在后来我写 SwiftUI 时也帮了大忙。2019 年苹果发布 SwiftUI它预告了一个全新的声明式 UI 时代。但商业项目不可能把 UIKit 一夜之间扔掉所以很长一段时间里我们都在用 UIHostingController 把 SwiftUI 页面嵌进 UIKit 的导航栈里或者在 SwiftUI 里通过 UIViewRepresentable 复用旧的地图组件、视频组件。这个过程让我深刻体会到iOS 生态升级快但迁移时讲究的是“渐进式”不是“革命式”。2.3 系统能力变化的适配清单过去十年的 iOS 大版本每个版本都带来几个必须处理的适配点我把它们整理成了一张几乎随身带的表。iOS 10 推出了 ATS要求 App 默认使用 HTTPS只对部分情况开放 ATS 例外。那年不少 App 为了省事直接在 Info.plist 里把 NSAllowsArbitraryLoads 设为 YES审核通过率开始下降苹果还发邮件警告。iOS 11 引入 iPhone X全面屏和安全区开始成为必答题我专门写了一篇文章记录自己因为忽略 safeArea 导致登录按钮被 Home 指示条遮挡的失败案例。iOS 13 带来暗黑模式和 Sign in with Apple如果 App 不支持暗黑模式至少要把 Info.plist 里的 UIUserInterfaceStyle 写死为 Light否则系统会自动用默认样式渲染出很难看的毛玻璃效果。iOS 14 是隐私元年IDFA 从默认可读变成必须弹窗授权很多做广告归因的团队原地崩溃我们当时被迫把整个数据上报体系从 IDFA 改成基于服务端生成的匿名 ID。iOS 16 的锁屏小组件、iOS 17 的交互式小组件则要求开发者重新理解 Widget 的刷新机制和 Timeline 模型。常有人说 iOS 开发是“苹果给什么你学什么”这话不假。但反过来看系统能力的每一次变化都是普通开发者拉开差距的机会。谁先读懂了 safeArea谁先适配了暗黑模式谁先摸清了 ATT 的逻辑谁就能在团队里获得更多话语权。3. 深水区的适配工程开发中最耗时间的部分3.1 屏幕适配的演进与方法屏幕适配是每个 iOS 开发者绕不开的体力活。2015 年我还在用宏定义判断屏幕宽度手动计算 frame比如把按钮的 x 坐标写成 (SCREEN_WIDTH - 100) / 2一旦横竖屏切换或者出现 iPad 多任务分屏界面就整个错位。后来切换到 AutoLayout 加 Masonry代码变成 views 之间的约束关系适配压力小了很多但新的问题又来了约束冲突。使用 Masonry 时如果同时给一个 view 设置了 leading、trailing、width 三个约束而它们的优先级又没有理清控制台会刷出一大堆 constraint conflict 警告你根本分不清哪些约束是多余的。我的调试方法是在 Debug 模式里为每条约束增加 identifier一旦出现冲突Xcode 会把这个 identifier 打印出来直接定位到代码里的那一行效率提升非常多。另外Masonry 的 make 语法里 recommended 的约束尽量和初始化 frame 一起设置否则容易出现“先布局后更新”造成的跳动。iOS 11 safeArea 出现后适配逻辑又换了一套。以前你是用 topLayoutGuide 和 bottomLayoutGuide 来避让导航栏和 TabBar后来统一改成 view.safeAreaLayoutGuide。对老项目做迁移时最怕的是手写 frame 的代码还残留New 控件在 iPhone X 以上机型完全不去遵守 safeArea底部按钮直接顶到 Home 条下面。我的经验是凡是新建页面一律基于 safeAreaLayoutGuide 做约束老页面做迁移时优先用 UIView 的 safeAreaInsetsDidChange 做一次补偿布局。这比逐行改 frame 要稳得多。2020 年之后我新项目基本都用 SwiftUI 的 View 体系布局自动处理安全区代码量比 AutoLayout 少了不止一半。但 SwiftUI 也有自己的坑比如对 ScrollView 里的懒加载机制理解不到位会导致列表在快速滚动时卡顿再比如某些系统控件的默认间距在不同 iOS 版本间有差异必须用自定义 ViewModifier 去统一。总体来说适配不是一次性工作而是每个大版本发布前都要做的例行检查。3.2 审核上架从被拒到通过的实战经验App Store 审核是 iOS 开发中最让人心累的一环。十年里我提交审核的大大小小版本有上百个被拒的次数量一只手数不过来。最常见的拒绝理由永远是那块让人闻风丧胆的 2.1 大礼包提交的 App 功能不完整、信息不清晰、体验太差苹果会用一套笼统的文案让你再次提交你还不知道自己错在哪里。另一个高频被拒点是 3.1.1 内购条款。如果 App 里有付费功能但没有使用 IAP 支付而是接了支付宝或微信支付被拒基本是板上钉钉。而且就算用了 IAP也有一个容易忽略的细节苹果允许用户在 App 内查看非数字商品的信息但不允许引导用户跳转到外部网页购买。我遇到过因为一个“了解更多”的按钮在审核环境中跳到了 H5 商城结果被苹果认定规避内购整包被拒。后来我把所有导流线索全部裁掉审核才通过。此外很多团队忽略隐私合规。从 2020 年苹果上线隐私标签之后你必须把收集的数据类型、用途、是否关联用户身份逐项列清楚。最真实的案例是一个 SDK 在后台获取了设备 MAC 地址代码层面我们根本没用但 SDK 有默认行为导致隐私问卷填报不实被苹果要求整改。当时排查了很久最终结论是“第三方 SDK 的隐私声明也要背锅”。所以现在我在选择第三方库时第一条就是检查它的隐私政策是否清晰其次才是功能和性能。审核策略上没有捷径我的经验就三条功能要完整、权限要最小、隐私要真实。3.3 崩溃治理与性能优化做 iOS 开发久了你会发现崩溃和卡顿是永远修不完的。我习惯把所有线上崩溃分成三类第一类 crashing 型App 直接闪退主要是内存问题、未捕获异常、主线程死锁第二类是卡顿型用户感知强烈但不崩溃通常是主线程做了大量 IO 或大量计算列表 cell 高度频繁计算第三类是逻辑错误型程序没有崩溃但结果错乱比如并发访问同一可变数组导致数据错乱。对第一类问题我常用的工具是 Xcode 的 Instruments 里的 Zombies 和 Leaks。Zombies 适合定位野指针Leaks 适合定位内存泄漏。用 Method Swizzling 做在线崩溃捕获也能解决一部分问题但要注意捕获动作本身别造成死循环。对第二类问题我一般用 Time Profiler 看主线程耗时函数以及用 os_signpost 做自定义埋点。真正的经验是不要凭感觉优化一定要用工具量化否则你优化的方向很可能是错的。启动时间优化也是性能里的大头。冷启动指的是用户点击图标到第一帧渲染完成之间的过程。2015 年的 App 冷启动 3 秒都算正常现在苹果要求理想情况下 2 秒以内否则用户流失率非常明显。优化的手段包括减少动态库加载数量、把不紧急的任务推迟到首帧之后、在启动阶段不做网络请求和数据库迁移。我接手过一个老项目启动时间接近 4 秒查了半天发现它竟然在启动时同步遍历了整个 Documents 目录去清理缓存光是这一步就耗了 1.5 秒。把同步改成异步线程后启动时间直接降到 2.1 秒。4. 跨平台围城uniapp、Flutter 与原生 iOS 的短兵相接4.1 为什么总会有人问你“原生值不值”大概从 2017 年开始我一个 iOS 原生开发者的身边就不断出现这样的声音“用 React Native 吧一套代码双端跑”“用 Flutter 吧性能更好”“用 uniapp 吧连小程序都能出”。尤其是近几年微信小程序普及开来很多业务团队的诉求是“先做个小程序试试水有量再上 App”。在这种对比里原生 iOS 开发似乎成了“成本高、周期长”的代名词。但真的是这样吗我认为要分场景。原生开发的优势在于对系统能力的最深度调用比如苹果新出的 WidgetKit、App Clips、Metal、Core ML只有原生 API 能第一时间完整使用而且审核、上架、性能调优这些环节原生团队踩过的坑一套体系很成熟。跨平台方案的优势则在于业务的快速验证尤其适合工具类、内容展示类、后台管理类产品它们对系统底层能力要求不高跨平台能把开发成本压缩一半以上。我做过的项目里有一个广泛使用的工具类 App一开始用 SwiftUI 原生开发前后花了两个月。后来产品线准备覆盖微信小程序和 Android 端如果每个端都单独开发团队至少要三条平行线。当时我们评估了 Flutter 和 uniapp最终选了 uniapp原因很简单它一套代码能同时编译到 iOS、Android 和微信小程序团队里只要有人熟悉 Vue就能快速上手。结果只花三周就把核心功能在小程序里跑通了。如果当时我坚持“原生为王”这个项目不可能这么快上线。4.2 uniapp 开发微信小程序的边界感用 uniapp 做了两个完整项目之后我必须承认它确实能在短时间内交付一个像样的跨端应用。你可以在同一个项目里编写 vue 页面通过 uni.request 发网络请求用 uni.navigateTo 做页面跳转然后通过 HBuilderX 一键生成 iOS、Android、微信小程序的代码包。对于业务逻辑相对简单、列表和表单为主的应用它的开发效率非常可观。但 uniapp 的边界也很明显。第一是性能瓶颈。微信小程序本身运行在 WebView 和 JSCore 之上uniapp 编译后的逻辑也不例外如果在页面里加载大量图片、频繁操作 DOM滚动流畅度会明显下降。第二是原生能力受限。小程序平台对蓝牙、NFC、后台位置等能力做了极强的限制uniapp 能调的 API 上限就等于微信给的能力上限一旦业务需要深度硬件交互你还是得回到原生。第三是生态问题。uniapp 里使用自带的 rich-text 渲染富文本时样式兼容性不如原生 TextKit地图、视频、直播等组件在不同端上的表现也参差不齐。所以我的建议是uniapp 适合做 MVP 验证、适合做活动页、适合做工具类小程序但如果你是做视频剪辑、实时音视频、蓝牙控制、复杂图形编辑还是老老实实走原生。跨平台的价值在于“业务逻辑共享”而不是“打破平台边界”。真要继续深挖Flutter 在渲染一致性上比 uniapp 更好但它又不能直接出小程序包这是它的另一个短板。4.3 Android/iOS/鸿蒙三端技术选型决策表2025 年再谈跨端开发已经绕不开鸿蒙。华为鸿蒙的 ArkTS 和方舟框架语法上有些 TypeScript 的影子组件模型又借鉴了声明式 UI对 iOS 开发者来说学习成本没有想象中那么高。我和鸿蒙开发团队一起协作过一个项目iOS 端用 SwiftUI鸿蒙端用 ArkTS两边在页面声明、状态管理、组件复用的理念上高度相似真正需要拉开的差异主要在系统 API 和生态上。下面这张表是我在实际项目中反复验证过的选型逻辑标注了不同方案在不同场景下的表现选型方案开发效率性能系统能力覆盖微信小程序团队技术要求适用场景原生 iOS中最高最完整不支持熟悉 Swift/OC深度依赖系统能力、追求极致体验原生 Android中最高最完整不支持熟悉 Kotlin/Java深度依赖系统能力、追求极致体验uniapp高中有限支持熟悉 Vue多端快速上线、中小型业务Flutter中高高较完整需额外桥接熟悉 Dart双端一致性高要求的应用鸿蒙 ArkTS中高鸿蒙全量不支持熟悉 ArkTS/TS面向鸿蒙生态、政企定制项目我个人的看法是做技术选型不是去看哪个框架热度高而是看团队的组成、产品的阶段和目标的平台矩阵。如果一个产品要同时运营 App 和小程序且预算有限uniapp 是最稳的起步选择如果一个产品要长期打磨体验且核心功能离不开硬件传感器原生依然是唯一解。iOS 开发者不必因为 uniapp、Flutter 的火热而焦虑原生经验里对内存、渲染、线程的理解放到任何跨平台框架里都是底层能力。5. 十年踩坑实录最常见的故障与排查技巧5.1 一次典型的 Block 循环引用事故复盘循环引用是 iOS 开发里最容易踩、也最隐蔽的坑。2016 年我在一个 IM 项目里写过一段代码一个 ChatViewController 持有聊天管理器管理器的 success block 里又引用了 self 去刷新 UI。表面看没有强持但 ARC 环境下block 被管理器保存后self 就被间接持有控制器退出聊天界面时始终不会释放内存持续上涨。这种问题在开发阶段几乎不可能被肉眼发现因为页面切换一次两次根本看不出来只有长时间使用才会触发内存警告和闪退。我当时用了三种手段定位先是在 dealloc 里打日志结果发现退出页面后 dealloc 永远不执行再使用 Instruments 的 Leaks 看循环引用路径最后用代码审查手动检查 block 里到底捕获了哪些变量。修复方式很简单把要使用的控制器改成 weak 引用或者使用 Xcode 提供的 block 捕获列表。修复之后还要检查这类问题在其他页面是否存在。从这之后我养成了两个好习惯。第一所有 block 属性都用 copy 修饰并在回调里优先用 weak-strong dance即先声明 __weak typeof(self) weakSelf self再在 block 内部用 __strong typeof(weakSelf) strongSelf weakSelf第二网络请求的 completion block 中避免直接持有 self尽量通过一个轻量的 ViewModel 对象来传递数据。这个小习惯让我后来少踩了很多内存坑。5.2 NSTimer 与 WKWebView 的两种“顽固”问题NSTimer 是我见过的最容易造成内存泄漏的系统组件之一。很多人知道定时器要在 dealloc 里 invalidate但忽略了 GCD 的 dispatch_source_t 定时器如果不断给主线程派发任务同样会让控制器无法释放。后来我统一封装了一个 YMTimer 类内部使用 block 加 target-action 解耦并让 timer 在持有者释放时自动停止。遇到 WKWebView 时问题更棘手。WKWebView 有自己的进程和内存缓存加载网页后占用的真实内存并不是马上释放即使把 webView 从界面上移除内存也可能居高不下。处理方式一般是在页面退出时手动调用 webView.configuration.websiteDataStore 清理网站数据并在 app 收到内存警告时主动清空 webView 的缓存。5.3 弱网环境下的请求重试与数据一致性移动端开发中弱网是常态。2019 年我们在一次户外直播场景里多次出现数据错乱用户进入直播间点赞数变成负数、评论列表重复、礼物列表显示错乱。排查后发现是网络层对“失败重试”缺少防护同一个请求在弱网下超时后自动重发而服务器没有做幂等处理于是同一笔礼物赠送被重复扣费。后来我们在请求层引入了 requestId 机制每次请求生成一个唯一标识服务器根据 requestId 去重客户端设置合理的超时时间从默认的 60 秒改成 15 秒并把重试次数控制在 2 次以内重试时机加上指数退避。这个改动听着不大但直接把线上投诉率降了一半。网络层的另一个隐蔽问题是 DNS 解析慢。国内部分网络环境对境外域名的解析经常超时解决方式一是改用 HTTPDNS二是把域名做多区域分线解析。早年我们在使用第三方统计 SDK 时就因为它们默认的统计上报域名解析慢导致启动时主线程卡了一会儿。后来所有网络请求都统一走了自己封装的网络层并追加了诊断接口App 启动时通过一个极轻量的小包来判断网络类型和调度环境再做针对性的超时调整。这种看似不性感的基础设施优化对用户体验的提升反而最明显。6. 一些给新人的实在建议6.1 建立自己的技能树而不是跟着框架跑我面试过不少简历上写着“精通 Flutter”“精通 uniapp”的候选人但深入聊下来很多人对内存管理、多线程、网络协议的理解停留在很浅的层面。说实话框架会过时语言会更替但操作系统、编译原理、数据结构、网络基础这些底层能力不会过时。我给新人的建议是如果你刚入门先用原生的 Swift 做两三个完整项目把 UIKit 或 SwiftUI 的布局、内存、生命周期搞清楚再去碰跨平台框架如果你已经工作了几年可以针对一个领域做深比如音视频、图形渲染、性能优化、底层网络不要在各种框架之间反复横跳。学习方法上我推荐按课题做“小闭环”。比如这周解决“内存泄漏”就从现象入手用 Instruments 复现、定位、修复再写一篇复盘笔记下周解决“启动优化”就动手打点、测量、优化。比看十遍文档不如亲手处理一个真问题。我个人这些年能保持成长靠的就是这种“遇到问题、记录问题、解决问题、形成方法论”的循环。6.2 复盘模板每一个合作项目都值得记录关于技术复盘我有一个一直沿用的模板问题描述、影响范围、定位过程、根因分析、修复方案、预防措施。比如前面提到的循环引用事故我用这个模板把现象、堆栈、修复方式、代码规范建议都记录下来后来同类问题一出现团队直接翻文档就能定位。内容不必追求长但一定要记录“为什么”而不只是“是什么”否则复盘就变成了流水账。2015 年到 2025 年我自己建立了本地资料库里面有超过 200 条这样的复盘记录覆盖了从崩溃、卡顿、审核被拒到跨端选型的各种问题。每次接手新项目时我都会把历史记录翻一遍看看哪些坑可能还会出现。有人觉得这是在自找麻烦但正是这种“笨办法”让我从当初一个面对业务需求手足无措的新人长成了今天能稳定带团队的老家伙。6.3 最后想说的一些心里话如果让我用一句话总结这十年的 iOS 开发之路那就是平台会变但解决问题的底子不会变。2015 年我在学 Objective-C、Masonry、FMDB2025 年我在写 SwiftUI 和 ArkTS 对比文档但十年里真正沉淀下来的是架构思维、排查问题和抽象业务的能力。当初一起入行的同事有人转去做产品有人去了管理岗也有人一直在代码一线大家都没有停止过学习只是方向不同。对于正在读这篇文章的人尤其是刚入行不久的新人我的建议是先静下心来把手头的原生项目做扎实不要被跨平台的浪潮推着走。uniapp、Flutter、鸿蒙这些新东西都可以学但不要让它们替代你对计算机基础的理解。只有把底层能力打牢你才不会被某个框架的兴衰绑住。最后再说一句我踩过无数坑之后最深的体会在 iOS 开发这条路上耐心比聪明值钱得多遇到问题别急着抄答案先把原因搞清楚你写下的每一行可靠代码都会在未来帮你扛住更大的项目。
返回列表