• 其实到现在为止 Swift 离替代 Objective-C 还是很遥远,因为 Apple 内部一直在用 Objective-C 来做一些 Framework 的开发,低层也不可能用 Swift 实现 — Cyan 如果把取代定义为编写底层框架的话, 至少以 Swift 3...

     

    其实到现在为止 Swift 离替代 Objective-C 还是很遥远,因为 Apple 内部一直在用 Objective-C 来做一些 Framework 的开发,低层也不可能用 Swift 实现

    — Cyan

    如果把取代定义为编写底层框架的话, 至少以 Swift 3 来说, 毫无疑问是不可能的.

    首先我们先去探究一下为什么苹果会选择 Objective-C 作为官方开发语言?

    Objective-C 是在 C 的基础上加上一层面向对象, 在编写高性能模块的时候, 可以直接使用 C, 在编写对于性能不高的业务模块时, 就使用原生的 Objective-C.

    目前苹果的框架, 底层实现都是使用 C , 然后再套上一层 Objective-C 去暴露外部接口. 这种方式既保证了性能, 又能保证 API 的易用性.

    而且苹果使用了大量的开源框架, 系统底层很多模块, 都已经有了开源的基于 C 语言的框架实现, 跟 C 的交互上, Swift 明显不如 Objective-C 那么方便.

    除开语言生态, 还有一个问题是 Swift 的性能不如 C, Swift 在公布的时候, 就宣称运行效率可以媲美甚至超越 C. 但这是有前提的, 没有运行时损耗的情况下 Swift 才有可能与 C 的运行效率持平.

    Swift 的运行时损耗到底来自哪里

    Swift 的运行效率损耗主要来自于 ARC, 内存管理, 运行的时候, 一个对象会不停地进行 retain 和 release, runtime 必须一直 observe 每一个对象的 retain count, 当 retain count 达到 0 的时候就释放这个对象. 而 C 就没有这个问题, 因为 C 没有对象, 没有运行时的损耗.

    那解决方式也就很简单了, 换一种新的内存管理模式就行了(Swift 实际做法是直接引入了一种新模式, 与 ARC 并存).

    目前主流的内存管理方式分三种:

    1. 手动: C 语言的 malloc 库, 特点就是无运行时损耗, 但不好控制释放内存的时机.
    2. 半自动: Objective-C 和 Swift 的 MRC/ARC, 有运行时损耗, 但基本上可以让程序员不用去考虑内存管理的问题.
    3. 自动的: Java/Go 的 GC. 基本上同上, 但需要在某个时间点去停止所有线程, 释放内存的时机不可控.

    Objective-C 的 MRC 还需要手动去写 retain/release, 在进化到 ARC 之后, 除了需要在类成员变量声明的时候, 显式地声明是 weak/strong/retain/copy就可以了, retain/release 的插入交给编译器即可, ARC 其实已经是实际上的自动化内存管理模式了.

    而 Swift 在把指针抽象为引用类型, 加入 Mutable/Immutable 的概念之后, 就只需要偶尔写写 weak就行了, 唯一需要对于内存管理费心的就是 retain cycle 的问题, 但也比之前省心很多了. 而且随着 Swift 工具链的发展, 这些问题都可以在编译期或者 Debug 时就暴露出来.

    半自动的内存管理, 实际上还有一种, 就是 Rust 的 OwnerShip, 我个人的理解是, 这种方式其实是 MRC/ARC 的一种延续, 但 MRC/ARC 内存释放的时机还是需要在运行时才能知道, 而 Rust 可以在编译期就解析出什么时候可以释放掉内存, 从而省略掉 retain/release 的存在, 也没必要专门跑一个 runtime 去监测对象的引用计数., 从而达到比 ARC 更高的运行效率

    仔细思考一下这种自动化的内存管理模式, 其实都是在把指针分类, 加上 context(上下文), 抽象出来, 暴露给编译器更多与关于指针的信息, 而不是单纯的一个内存地址, 从而让编译器可以分析释放对象的时机.

    Rust 也不例外, 既然要达到比 ARC 更高的运行效率, 那就必然要提供给编译器更多的指针信息, 因此在指针声明和传递时都需要显式地声明所有权, 代码量也会相应地增多, 对于程序员的要求也会更高.

    虽然写起来比 ARC 更麻烦一点, 但也比 C 那种原始的方式简单很多, 提供给了 Rust, Swift 这些”现代编程语言”编写底层程序的可能性.

    补充:学术界对于 GC 的研究已经很多了, 但关于 ARC 的研究还是很少, ARC 还有很大的进步空间. 甚至说如果可以在编译期就检测到对象实际释放的时机的话, 就可以直接省略掉中间的那些 retain/release, 不必在运行时再去检测是否应该释放掉这一段内存.

    Swift 什么时候会引入这种内存管理模式

    在我写这篇文章的时候, Swift 团队正式发布了引入 OwnerShip 的提案(正式方案?), 喵神大大也翻译了这篇文章, 更多技术细则可以去看喵神大大的翻译.

    一句话总结: Swift 的团队希望 Swift 能够进化成为一门系统编程语言, 所以才不惜牺牲 ABI 稳定性去加入这个 Feature.

    Swift 是为了取代 Objective-C 而生的吗

     

     

     

    在 Cyan 大大的那篇文章下面, 有这么一条回复.

    LLVM 之父, Swift 的作者之一 Chris Lattner 在 ATP 的一期访谈里聊过这件事情, 直接贴原话:

    There's a ton of stuff to love about Objective-C, and while there are a few things that are ugly about it, some “@“ signs and semicolons and other stuff like that, we can make Objective-C better. The question was always: Why not just make Objective-C better? Why don't we just keep evolving Objective-C? Why do we want to face potential disruption in terms of moving the entire development community to something [23:00] new?

    We kicked that around for a long time. We talked about both sides and we came to realize that, yes, we can and should make Objective-C better, and we continued to invest in Objective-C. We did things like ARC, for example, which is a major effort, but…

    We were talking about, okay, can we just make Objective-C better and can we feature-creep it to the language we want for the fullness of time? Because if we can, that would be much less disruptive to the community. We decided that, yeah, we can move Objective-C a lot closer to what we want so we can get automatic memory management with ARC, for example, but we can't ever take away the problems that lead to Objective-C being unsafe. The fundamental problem was Objective-C was built on top of C. [24:00] C inherently has pointers. It has uninitialized variables. It has array overflows. It has all these problems that even if you have full control of your compiler and tool stack, you just can't fix. To fix dangling pointers, you would have to fix lifetime issues, and C doesn't have a framework to reason about that, and retrofitting that into a compatible way into the system just wouldn't really work.

    If you took away C from Objective-C, you couldn't use C arrays on the stack, for example. And if you [24:30] couldn't do that, there's entire classes of applications where the performance just wouldn't be acceptable. We went around, around, around. We said the only way that this can make sense in terms of the cost of the disruption to the community is if we make it a safe programming language: not “safe” as in “you can have no bugs,” but “safe” in terms of memory safety while also providing high performance and moving the programming model forward.That was really kind [25:00] of the ideas that came together to make Swift being worth the investment and being worth being disruptive to the community. A lot of these kinds of pitches and ideas were being held in very small, small, small meetings. Coming out of WWDC 2013 is when we and the executive team decided okay, let's really commit to this, and that’s when the developer-tools [25:30] team came to know about it and really started working hard on it.

    — 节选自 Accidental Tech Podcast: Chris Lattner interview

    内容有点长, 大家可以看一下我高亮的部分, 实际上苹果的团队也很犹豫, 到底要继续优化 Objective-C, 还是应该发明一门新的语言. 最后两种方式都尝试一下, 然后 Objective-C 就有了 ARC, 点语法等等新功能.

    但最后, 苹果的团队发现 Objective-C 这门语言不安全最关键的原因还是因为它是基于 C 语言的, 它有指针, 它有不完全初始化的变量, 它会数组越界. 即使苹果的团队对于工具链和编译器有完整的控制权, 也没办法很好地解决这个问题.

    苹果的团队想了又想, 反复思虑之后, 还是决定打断整个开发社区, 去创建一门 Safe的编程语言, 不只是那种没有 bug的 Safe, 而是保持安全的同时还能提供高性能的, 推动整个编程范式前进的那种 Safe.

    Swift 与 Objective-C 并非是对立的, “Objective-C is Great”, Swift 只是苹果提供的一个 “better option”.

    ABI Stability vs. API Stability

    关于是否应该主力 Swift 另一个关键的争论点在于, ABI 不稳定.

    因为 Swift 的 ABI 不稳定而放弃 Swift 的人好像特别多. 可是我看到的很多文章都没有提到到底 ABI 稳定对于我们应用开发者代表着什么? ABI 与 API 又有什么区别?

    ABI (Application Binary Interface)

    在计算机中,应用二进制接口(英语:application binary interface,縮寫為 ABI)描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口。

    … ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。

    — zh.wikipedia.org/wiki/应用二进制接…

    ABI 主要是描述程序跟操作系统之间的低级接口, 说白了就是Swift 二进制程序与系统或者其它程序交互时会调用的接口, 一般这部分都是由编译器去处理, 除非我们进行很底层的开发, 或者是想要 hack 编译过程(例如把 Swift 编译到 JavaScript) 才会需要去考虑这方面的东西.

    ABI 的不稳定会造成以下结果:

    1. 打包 Swift 程序时, 必须嵌入一个 Swift 标准库.我们每次打包应用时, 都需要嵌入一个 Swift 的标准库, 因为系统不知道我们使用程序时用的 ABI 是哪个版本, 所以必须没办法在系统内部内置一套标准库. 用过 pyenv, rvm 或者 nvm 的人就大概知道这里的过程.
    2. 第三方 SDK 开发困难. 你的应用与第三方 SDK 使用的 ABI 版本如果不同就会出现问题, 例如说 Swift 2和 Swift 3打包出来的库就没办法互相调用. 非要支持的话, Swift 每出一个版本就需要跟着打包一个 SDK, 而且之前的 SDK 没办法向后兼容.

    ABI 的稳定到底意味着什么

    说明完了 ABI 是什么, 以及 ABI 不稳定会造成什么.

    那 ABI 稳定对我们有什么实际意义? Chirs 在 ATP 里讨论过这个问题, 继续贴原话:

    Another part of it is that ABI stability is super-important, but it's not as important as people think it is for application developers. It's really important to Apple, [51:30] but what we realized in the Swift 3 timeframe is that the thing app developers would benefit from the most was actually source stability. Who actually wants their application to be broken when they get a new version of Xcode? Really nobody, right?

    ABI 稳定超级重要, 不过对于应用开发者来说, 并没有大家想象的那么重要. 但是对于苹果来说很重要. 我们相信在 Swift 3 之后, 应用开发者受益最多的还是代码稳定(API Stability), 谁愿意升级了一下 Xcode 就运行不了自己的程序呢?

    ABI 的稳定对我们来说真的没有那么重要, 大厂开发 SDK 也只要选择 Objective-C 就行了(所以不能用 Swift 才是痛苦的地方?). 再给点力的话, 底层使用 Objective-C 实现, 用 Swift 负责暴露外部接口也行(例如 Instagram 开源的 IGListKit), Swift 版本迁移的工作就会大幅减少了. ABI 不稳定最痛苦的其实是苹果的底层开发人员, 他们必须实时去更新框架对外的接口, 想办法让官方框架去兼容不同版本的 Swift.

    补充: 写这篇文章的时候, 柏学网翻译了 Swift 官方关于 ABI 稳定的声明, 大家可以去看看

    API 稳定还会是问题吗

    Halfway through the release, we pivoted and source stability became the goal, so I'm really excited that when Swift 3.1 or Swift 4 comes out that it's still going to be able to build [52:00] Swift 3 code, and even if there are minor changes that need to be made for one reason or another, that you can upgrade and you have great compatibility with your old code and you don't have to start the migrator before you can do anything. So it's going to be a great improvement for people's lives.

    Swift 4的开发途中, 我们定下了一个目标, 无论是在 Swift 3.1 还是 Swift 4 里, 都必须可以编译 Swift 3的代码(编译器提供相应的编译模式)

    API 不稳定导致的代码迁移, 可能 Swift 1 到 Swift 2 对于大家的冲击太大, 所以大家才会有那么深的怨念, 我没有经历过那一段日子没有发言权.

    但 Swift 2 到 Swift 3 的迁移我是经历过的, 公司项目刚起步, 一万多行代码左右, 自动转换加上一个晚上我就让程序成功跑起来了, 随后一个星期修修 bug, 适配一下新的 Feature 也就完全过度过去了, 后来陆陆续续看了 Enjoy, Airbnb 等等关于 Swift 迁移过程的讲述, 过程其实也没有很痛苦. 但 CoreGraphic 等框架的 Swift 化带来的麻烦可能会更多一点, 代码耦合度太高的项目可能会在这里陷得很深. 

    Swift 3 之后会好很多, Swift 4的编译器提供了 Swift 3的编译模式, 至少我们可以慢慢地去迁移我们的代码, 而不是一升级 Xcode 就连程序也跑不起来.

    API 之后肯定还会改的, 但其实从 Swift 2 到 Swift 3 的过程里, 我觉得很多原则性的东西其实已经稳定下来的, 接下来的改动要么就是很小, 要么就是特别有规律性, 迁移的时候花点时间去看看第三方发的迁移指南, 就可以很平稳地迁移过去了.

    一句话总结: ABI 不稳定对于我们应用开发者的影响并没有那么大, API 之后虽然会变, 但之后肯定会给你充足的迁移时间

    Swift 之我见

    说了这么多, 希望大家现在可以理解 Swift 的团队到底是基于什么样的原因, 才做出了各种决策, 才演变出了现在的 Swift.

    最后, 我想聊聊自己对于 Swift 的见解.

    Swift 目前的问题

    代码稳定, 其实都是小事情, 迁移, 几十万行代码, 分配给所有人, 最多也就是一个星期的事情. Swift 的开发者都很积极, 主流的第三方框架基本上两个星期内都能更新到最新的版本, 我用的库 75% 都从 beta 时期就开始跟进 Swift 的更新.

    Swift 3 最大的问题我觉得还是工具链不稳定

    • 增量编译做的不好. 编译随时 Segment Fault, 必须 clean 一次才行.

    • 超长的编译时间. 每次编译出错, clean 之后可能需要编译七八分钟, 之前我记得还有人总结了一份什么样的语法会导致编译时间变长的列表, 为了编译时间缩短而却强行改变代码应有的样子, 我觉得很不值得.
      我采用的解决方式就是把底层模块抽出来, 独立成一个框架, 使用 Carthage 去进行包管理, 全部编译成静态库, debug 编译的时候, 只要链接上去就行了, 大大减少编译时间. (顺带一说, Carthage 是用 Swift 写的)

    • 代码高亮随时崩, 代码补齐几乎没有. Xcode 很容易变白板, 我个人而言发生情况不多, 一天能遇上个两三次左右, 但是代码补齐就真心是完全没有, 每天基本上都是盲打, 只有像是 UICollectionElementKindSectionFooter这种才会等等代码补齐. (补充一下, AppCode EAP 对于 Swift 3的支持异常的好, 补齐跟高亮都能够很好地满足日常需求, 我的 Air 8g 内存就能跑的很好)

    这两个问题虽然很小很不起眼, 但对我日常工作影响是最大的.

    之前 Chris Lattner 离开苹果加入特斯拉的消息大家应该都知道, 但 Chris 依旧保留自己在 Swift 开发小组的位置, 而实际上 Chris 在苹果也只有很小一部分时间分配给 Swift(LLVM 对于这个世界影响更大一点), 接任的 Ted, 实际上也是之前实际上的 Swift 开发小组组长, 他之前也是 Rust 的主要开发者之一, 第一版的 Clang 静态分析器也是 Ted 一个人撸出来的.

    Chris 平时主要负责提一些”天马行空”的想法, 打乱掉开发小组的计划, Ted 负责把这些想法落地.

    Ted 个人更倾向于优化编译, 提高开发体验, 比起 ABI 稳定优先级更高, 但具体决策还是得根据具体情况去决定.

    虽然开发体验对我来说也很重要, 很难割舍, 但我隐约感觉无论是外部, 还是苹果内部, 留给 Swift 开发团队的时间可能不会特别多了, 加紧开发功能性的东西, 赶快稳定 ABI 可能会更加重要.(只是个人感觉, 单纯的个人感觉)

    Swift 目前的热度主要还是因为 iOS 平台的强势, 继续加强什么语法糖, 优化开发体验, 最终也只会把 Swift 坑进 iOS 里, 只有让 Swift 变得更强大, 能够在更多领域有所发挥, 才能反哺 Swift, 让 Swift 变成一门伟大的语言. 

    Swift 很 Apple

    Swift 吸收了很多语言的特点, 以至于各种不同语言的开发者写 Swift 的时候都会觉得特别熟悉特别亲切. Chris 说 Swift 并不是想成为某一门语言的加强版, 也不是在模仿哪一门语言, Swift 只是想做到最好, 而想要做到最好就必须去吸收现有语言的优点, 通过某种方式去把它们糅合到一起. 类似的一句话, 乔布斯也说过, “我们不是刻意在模仿谁, 只是想做到最好, 如果做到最好需要学习别人的一些地方, 那就学习呗”, 这些都只是过程罢了, Best 才是结果.

    Swift 的 ABI 不稳定, 影响最大的其实是苹果自己, 但因为 Swift 想成为更好的语言, 所以一再拖延. 延期, 回炉再造, 然后再拿出一个最好的”作品”, 就像苹果的其它作品.

    Swift 还很不成熟, 各种意义上都不成熟, 需要做的事情很多, 泛型系统, 内存管理模型, 性能, 异步模型, POP 的探索, 编译的优化, ARC 的优化, 函数派发机制, 字符串处理, 更好的异常处理……

    结语

    Swift 对我来说是一种浪漫, 一种对于苹果文化的崇尚.

    推荐阅读:

    展开全文
  • Objective-C调用Swift 2014-08-17 17:05:05
    Objective-C调用Swift如果已经有了一个老的iOS应用,它是使用Objective-C编写的,而它的一些新功能需要采用Swift来编写,这时就可以从Objective-C调用SwiftObjective-C调用Swift时不需要桥接头文件,而是需要Xcode...
  • Objective中调用Swift代码 2014-12-14 13:12:43
    2、选择创建bridge-header,后会生成两个文件,一个是bridge-header(这个暂时没用,这个文件是用来将objective c中的接口暴露给swift),一个是swift文件 3、在swift中想要暴露给objective C中的类或者方法前加上@...
  • Objective-C的语法比较复杂,学习成本非常高,其复杂主要体现在它的类的创建、函数的实现和其他的高级特性上。 Swift是2013年苹果发布的一种新的iOS开发语言,其目的在于替代复杂的Objective-C。Swift的设计借鉴了...
  • 本指南介绍了SwiftObjective-C兼容性的三个重要方面,您可以在开发Cocoa应用程序时将其利用它: - **互操作性**让您可以在SwiftObjective-C代码之间进行交互,允许您在Objective-C中使用Swift类,并在编写Swift...
  • SwiftObjective-C API的交互 2016-04-18 17:13:39
    互用性是让 SwiftObjective-C 相接合的一种特性,使你能够在一种语言编写的文件中使用另一种语言。当你准备开始把 Swift 融入到你的开发流程中时,你应该懂得如何利用互用性来重新定义并提高你写 Cocoa 应用的...
  • Swift调用Objective-C 2014-08-15 19:15:56
    Swift调用Objective-C需要一个名为“-Bridging-Header.h”的桥接头文件,如下图所示。桥接头文件的作用是为Swift调用Objective-C对象搭建一个桥,它的命名必须是“- Bridging-Header.h”,我们需要在桥接头文件中...
  • SwiftObjective-C混合编程 2014-09-28 17:55:10
    假设你现在就是一个iOS程序员,你对Objective-C很熟悉,对iOS开发也很熟悉,然而,苹果公司在iOS 8之后推出了Swift语言。那么,如何才能快速地从Objective-C过渡到Swift呢? 本章我们将重点讲解如何从Objective-C...
  • DATE: 2019-3-2: Objective-C和Swift的区别
  • Objective-c调用Swift 2019-01-07 09:32:58
    Objective-C中使用Swift,步骤相似: 1、首先创建一个Objective-C的项目: Paste_Image.png 2.加入一个Swift的类文件: Paste_Image.png 3、点击Next,弹出一个对话框,选择YES Past...
  • SwiftObjective-C的联系 SwiftObjective-C共用同一套运行时环境我们编写程序,让程序运行起来,被机器执行的代码并非全部是由我们自己来编写的。需要同时运行很多预先写好的支持性的代码,才能让我们自己的代码...
  • <p>Apple mentioned that they could co-exist in one application, but does this mean that one could technically re-use old classes made in Objective-C whilst building new classes in Swift? <h1>The ...
  • iOS开发应该选择Objective-C还是Swift,这里会给出你选择:1.如果你想成为一个iOS开发者,你仍然需要学习Objective-C。2.Objective-C比Swift更容易学习。3.一旦你学习了Objective-C,学习Swift就很容易了。
  • 主要介绍原有 Objective-C 中的一些类型在 Swift 中的操作问题。差不多就能知道,你在 Swift 如何对 Objective-C (Foundation) 原生类型进行操作以及和 Swift 类型互转。 瞎写的,有错或者不明白的地方直接告诉我...
  • Objective-C里调用Swift 2016-03-22 15:00:39
    如果已经有了一个老的iOS应用,它是使用Objective-C编写的,而它的一些新功能需要采用Swift来编写,这时就可以从Objective-C调用Swift
  • 如果你正要从Objective-C过渡到Swift,或反过来,一个在两种语言间显示等效代码的小手册会很有帮助。本文内容就是这些:苹果开发者的红宝书,包含变量,集合,函数,类等等。下面例子中,上面是Objective-C代码,...
  • Swift是对ObjectiveC进行的封装,而且目前许多的第三方SDK以及第三方开源库都使用的ObjectiveC语言进行编写,因此许多的时候都需要Swift调用ObjectiveC内的方法。 下面简单的介绍下如何实现Swift调用ObjectiveC内的...
  • Objective-C, C++ and Objective-C++: an Updated Summary)。之所以做为一篇文章,是因为在实际项目中用到了这种混合,加以记录。 首先需要澄清的是,Objective-C是strict superset of C. C++是基于C语言的面向...
  • 摘要: SendBird是国外一款针对移动App和网站的Chat API,其开发团队成员Jed Gyeong分享了他们在将产品从Objective-C向Swift转换过程中所学习到的一些心得体会。 SendBird为常见系统均提供了示例UI,方便开发者构建...
1 2 3 4 5 ... 20
收藏数 23,130
精华内容 9,252