在我上一份工作中,我在 Audible(Audible 的各位,如果你们看到了这篇文章,请打个招呼!),我领导了将剩余的 Objective-C 代码移植到 Swift 的工作。当我开始这个项目时,Objective-C 代码大约占 25%;当我退休时,这个比例已经降到了个位数(而且我听说之后还在继续下降)。
为什么要这么做?那可是能正常运行的代码啊!难道我们不知道不能重写已经运行的代码吗?
为什么要放弃 Objective-C?
我们知道一些事情:其中之一是,我们的 Objective-C 代码中存在着许多导致程序崩溃的 bug 和未来可能导致程序崩溃的 bug(以及各种类型的 bug)。
所以,代码虽然能运行,但我们知道里面隐藏着很多崩溃点,而且有些崩溃点就像埋伏的猎手,伺机而动,潜伏多年才发动攻击。最好的办法就是用更安全的 Swift 语言重写一遍。
我们还知道,Swift 和 Objective-C 之间的互操作性非常差。这通常意味着要简化 Swift 代码,并且不能使用现代特性,从而限制了我们编写优秀 Swift 代码的选择。
第三,我们知道的是,我们公司里很少有工程师有Objective-C编程经验。维护Objective-C代码——修复bug、添加功能——比维护Swift代码成本更高。(这还用说吗?当很多工程师参与一个项目时,最好使用大家都熟悉的语言。)
当然,事情也并非一帆风顺。
顺便说一句,这样做仍然存在风险。重写代码始终存在风险。
我曾经负责修复一个漏洞:我们向某个 API 发送了一个整数,但它本应是布尔值——因为原始代码使用了 NSNumber,而 NSNumber 的数据类型并不明确。这导致推送通知部分中断,我粗略估计,这给公司造成了数十万美元的损失。
(真的吗?就这么个小bug?一个该死的NS编号就花了这么多钱?没错。Audible的规模或许比不上Facebook,但远远超过独立应用的规模。在加入Audible之前,我一直在用户规模较小的公司工作——参与一个拥有数百万用户的项目,既令人大开眼界,又令人胆战心惊。)
但关键在于:这恰恰证明了我的观点。如果有人试图用 Objective-C 来维护这段代码,很容易犯同样的错误,导致同样的故障。我们用 Swift 代码替换它时,代码类型是安全的:它明确地是一个布尔值,而不是整数(在我们修复之后;一开始正好相反)。用 Swift 替换 Objective-C 代码显然是明智之举。
再见了,那些方括号!
我没数过我的项目到底重写了(有时甚至只是删除了)多少行 Objective-C 代码。反正数量惊人。这些代码行数加起来,足以写好几个完整的应用程序了。
如果你查看NetNewsWire 的代码,你会发现它几乎完全是用 Swift 编写的,只有少量 Objective-C 用于各种解析器和 FMDB。它不仅是一个 Swift 应用,更是一个使用 async/await 和结构化并发的现代 Swift 应用。(大部分是现代的——还有一些代码需要更新为 async/await。这项工作仍在进行中。)
我说以上种种,是为了表明我并不墨守成规;我不是那种明明证据确凿却仍然坚持Objective-C至上的人。我是那个欣喜若狂地(哎呀,对不起Audible市场部,搞砸了)彻底抛弃Objective-C的人!
我想提前让你们知道以上所有内容,因为在我的下一篇文章中,我将谈谈我如何用 Objective-C 编写了一些新代码,并且非常喜欢它。
原文: https://inessential.com/2026/02/18/why-not-objective-c.html