Swift与ARC之前的Objective-C不兼容吗?

时间:2014-06-07 13:40:55

标签: objective-c automatic-ref-counting swift

我开始将Swift文件添加到一个非常大的遗留的Objective-C项目中,该项目不使用ARC。

编译项目时,我会收到ProjectName-Swift.h网桥标题中发出的每个属性的警告:

  • 未指定'assign','retain'或'copy'属性 - 假定'assign'为
  • 默认属性'assign'不适合非GC对象

似乎Swift正在发布基于ARC的Objective-C代码。

这是Swift特定版本中的限制/错误,还是Swift只能用于ARC代码?

3 个答案:

答案 0 :(得分:10)

您可以混合使用ARC和非ARC代码。所有ARC编译的代码都会自动管理用户的内存。您应该为项目启用ARC,然后使用-fno-objc-arc为单个文件禁用ARC,或者使用-fobjc-arc仅为Swift文件启用ARC(这可能没有必要,因为编译器可能会自动添加它)。 Swift代码最终被编译为使用相同的Objective C运行时,编译器插入的ARC调用与Objective C中的相同。编译后,ARC和非ARC代码的行为相同。

答案 1 :(得分:0)

  

当我编译项目时,我会收到ProjectName-Swift.h网桥标题中发出的每个属性的警告

一旦我将所有文件转换为ARC,我就能摆脱警告。 (不使用-fno-objc-arc

答案 2 :(得分:0)

Swift为Obj-C生成的头文件似乎假设在您的Obj-C代码中使用了ARC。根据您的Xcode版本和构建设置,您可能会启用警告,只要属性隐式为assign - 属性就会发出警告,这只是非ARC代码中的情况,如ARC代码中所示,属性是隐式的strong(与非ARC代码中的retain完全相同)。启用该警告后,每次将生成的标头导入非ARC的.m文件时,您都会收到该警告,并且Swift尚未为该属性设置存储属性。

但是这个警告并不意味着编译后的代码以后不会正常工作。尽管编译器认为此属性仅为assign,但肯定不是assign,因为Swift属性甚至不能是assign,它们可以是strong或者weak可以是weakassignweak不一样!nil - 当对象死亡时,属性变为assignassign - 属性变为悬空指针仍然指向对象过去居住的地址)。尽管有警告,这可能导致的最糟糕的事情是静态代码分析器结果不正确,因为分析器也可能会警告您assign - 属性如何破坏您的代码并且再次,分析器错误,因为属性简单实际上不是strong

要解决这个问题,唯一需要的是在默认情况下永远不要依赖属性,并始终正确地将所有属性标记为strong,这也适用于非ARC代码({{1} }和retain只是编译器的同义词,它对待两者完全相同,因此两者都可用于非ARC代码)。有趣的是,这正是Swift所做的。我在生成的标题中有大量的strong属性,但显然有些情况下Swift不会这样做(也许这实际上是一个Swift错误)。

这个问题的简单工作就是在导入生成的标题时禁用警告,这可以按如下方式完成:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-property-no-attribute"
#import "xxx-Swift.h"
#pragma clang diagnostic pop

将其打包到另一个头文件中,例如My-xxx-Swift.h然后只在代码中的任何位置导入My-xxx-Swift.h

我不会为整个项目禁用它(例如在Xcode构建设置中),因为通常这个警告非常有意义,可以帮助防止在混合ARC和非ARC代码时出现可怕的错误,可能是属性我们确实没有您认为的存储属性,因此在混合使用ARC和非ARC时,强烈建议您不要依赖隐式属性并始终使存储明确。