我开始将Swift文件添加到一个非常大的遗留的Objective-C项目中,该项目不使用ARC。
编译项目时,我会收到ProjectName-Swift.h
网桥标题中发出的每个属性的警告:
似乎Swift正在发布基于ARC的Objective-C代码。
这是Swift特定版本中的限制/错误,还是Swift只能用于ARC代码?
答案 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
可以是weak
(assign
与weak
不一样!nil
- 当对象死亡时,属性变为assign
,assign
- 属性变为悬空指针仍然指向对象过去居住的地址)。尽管有警告,这可能导致的最糟糕的事情是静态代码分析器结果不正确,因为分析器也可能会警告您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时,强烈建议您不要依赖隐式属性并始终使存储明确。