月度归档:2016年08月

Swift语言的兼容性问题

从Swift 3开始,可以认为Swift源代码级别兼容是没有问题的了,即Swift 4的编译器可以直接正确编译Swift 3的代码,而不需要像Swift 2到3或者Swift 1到2那样必须进行代码迁移。

原始信息在这:Swift Evolution,特别注意下面这段话

The primary goal of this release is to solidify and mature the Swift language and development experience. While source breaking changes to the language have been the norm for Swift 1 through 3, we would like the Swift 3.x (and Swift 4+) languages to be as source compatible with Swift 3.0 as reasonably possible. However, this will still be best-effort: if there is a really good reason to make a breaking change beyond Swift 3, we will consider it and find the least invasive way to roll out that change (e.g. by having a long deprecation cycle).

这段话的最重要的信息是,尽管Swift 1到3,经常出现源代码不兼容的情况,Swift社区还是决定从Swift 3.x开始,尽可能保证之版本的Swift与Swift 3是源代码级别兼容的。然而,如果Swift社区觉得非常有必要的话,也还是会做出一些语言上的重大变化,只不过这一次社区将尽可能的用温和的方式。所以,大家从Swift 3开始,不需要过于担心升级Xcode以后大量代码编译不通过的问题了。

然而,Swift 3到4的二进制兼容是没有保证的,所以,Swift 3编译出来的的framework,那是不可以用到Swift 4的工程中的。

详情见Rewrite the Swift 3 “goals” and drop the “nongoals” section, now that it的内容,大家可以看到

* **Stable ABI**

部分被删除了,也就是说Swift 3和以后版本的Swift的二进制兼容是大概率不可能的了,你用Swift 3编译的静态库和动态库,那是不能用到Swift 4工程上的。

如果你要对外发布framework,那么,暂时不要用Swift编写framework。

如果你的代码以开源的方式对外发布,并且他人的集成方式也是源代码集成的话,你大可以可以安心了,不需担心要像之前那样,swift1一个分支,swift2一个分支,swift3一个分支,并且三个分支互不兼容。Swift 4的工程也可以使用Swift 3的代码,正如你可以在C++源文件中写C代码,在Objective-C++的mm文件中写C++代码。

继续谈谈Found an unexpected Mach-O header code: 0x72613c21

之前一篇文章中,我提到,我使用Xcode 8 Beta 2打开之前的工程,并将Swift 2.2的代码转换为Swift 3之后,再度编译工程,Xcode就会报错误Found an unexpected Mach-O header code: 0x72613c21

正好,Apple Developer Forums也有一个Thread提到了0x72613c21错误。
该文指出问题出在Fabrics/Crashlytics上,如果你遇到了Found an unexpected Mach-O header code: 0x72613c21错误,那可能是你集成了Fabric/Crashlytics,并且版本不够新,因为许多人反应,移除Crashlytics后就好了,或者升级Crashlytics到3.7.2也可以。

不过,我当时的做法既不是移除Crashlytics,也不是升级Crashlytics,而是直接废除了Swfit代码,完全用Objective-C重新实现了原来Swift代码所实现的功能。

该Thread的最后一篇回复是这么说的:

diego.trevisan
Aug 1, 2016 2:02 PM
(in response to davidfromsparks)
This is finally fixed in Beta 4!

diego.trevisan
2016年8月1日,下午 2:02
(回复:davidfromsparks)
这个问题终于在Beta 4中解决了!

看到8月1日的回复,我可以郑重告诉大家,如果你遇到了0x72613c21错误,并且还在用Xcode 8 Beta 4之前的版本,那请首先尝试升级Xcode 8到Beta 4或更新版本。

diego.trevisan
Jul 31, 2016 3:43 PM
(in response to jmac)
I have just another dependency which is Alamofire and it is build from their new swift2.3 branch. Anyway, removing Fabric/Crashlytics solves the problem. Just tried adding them again, and the error appears :/
我的工程中有一个依赖Alamofire,而Alamofire是以swift2.3的分支编译的。无论如何,我将Fabric/Crashlytics从工程中移除了,Xcode 8就不会报错,而我一旦将Fabric/Crashlytics添加到工程中,那么错误就会重新出现。

jmac
Jul 31, 2016 4:33 PM
(in response to diego.trevisan)
This would be an interesting test:

– Take the Fabric.framework and Crashlytics.framework that you have from the installer, and try linking them by hand with a sample project with no other dependencies. Based on what you’re seeing, I would expect that it would not be able to build with Xcode 8 and that you would see the same Mach-O error.

如果你通过Fabric的安装包集成了Fabric.framework 和 Crashlytics.framework,并尝试在一个样例工程中仅仅链接这两个framework,且不包含其他的依赖. 那么,根据你所看见的,我预计Xcode 8无法成功编译该工程并且会报告Mach-O错误。

Then, try installing Fabric/Crashlytics in your project via Cocoapods. I was installing them via pods when they worked for me (and the older versions that I had were from the installer). I had assumed that the difference was just the old ones vs the new ones, but it’s possible that something about the way crashlytics links them ends up being different from what the installer does.

接下来,你可以试着用Cocoapods而不是Fabric的安装包集成Fabric/Crashlytics。我用Cocoapods集成Fabric/Crashlytics,这不会导致Mach-O错误(当然,我用Cocoapods安装的是新版本的Fabric/Crashlytics,而之前用安装包安装的Fabric/Crashlytics的版本旧一些)。我估计导致错误的原因仅仅是Fabric/Crashlytics的版本的新旧,新版本的没问题,旧版本的有问题,但是,或许也还有别的可能性,或许用安装包安装的Fabric/Crashlytics在Xcode链接静态库的时候与Cocoapods的方式有着细微的差别,而这个差别导致了Mach-O错误。