对于ObjC,可测试性直接改变符号的可见性。 默认情况下,ObjC代码中的所有符号在Swift中都被视为public,但类除外,它们在Swift中被视为open。 您可以将符号声明为__private_extern__,在这种情况下,它们的行为类似于Swift中的internal;您也可以将某些符号声明为static(而不是类或协议),在这种情况下,它们的行为类似于Swift中的fileprivate。 在Xcode构建设置中,您可以启用Symbols Hidden by Default,它会自动声明所有符号为__private_extern__,除非它们是static。在当前模块之外可见的符号必须使用__attribute__((visibility("default")))标记为公共符号,例如,您可以使用define:
#define public __attribute__((visibility("default")))
public
@interface MyClass : NSObject
当您启用可测试性时,默认的可见性被重新设置为public,从而覆盖Xcode构建设置Symbols Hidden by Default。同时,定义__private_extern__也被更改,也意味着公共可见性。只有static符号保持隐藏。
注意:**如果手动添加编译器标记-fvisibility=hidden,默认情况下会强制隐藏所有符号,就像构建设置Symbols Hidden by Default一样,但是这不能被可测试性覆盖。另外,如果使用__attribute__((visibility("hidden")))显式标记隐藏符号,这也不能被覆盖。
2条答案
按热度按时间sauutmhj1#
我在追踪另一个问题时偶然发现了这个问题。但是也许我可以提供一个场景。为什么你不想启用可测试性呢?
如果你想使用GCC_SYMBOLS_PRIVATE_EXTERN(aka Symbols Hidden By Default),启用可测试性有更高的优先级,并且会覆盖它。
在我的例子中,我有一个从Debug复制的配置,因此启用可测试性== YES。我有一个外部静态库,它是用-fvisibility=hidden构建的,用于构建我自己的静态库之一(用Xcode构建)。然而,当构建我的调试构建时,我得到了错误,例如(我编辑了函数名和路径)
显示所有消息:函数中的直接访问...意味着弱符号在运行时不能被重写。这可能是由于使用不同的可见性设置编译不同的翻译单元造成的。
从苹果的文档这里:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html
当您将Enable Testability build设置设为Yes时(对于新项目中的测试构建默认为true),Xcode会在编译过程中包含-enable-testing标志,这使得在编译模块中声明的Swift实体有资格获得更高级别的访问权限。
看起来它也是Swift的可访问性,所以如果你不使用Xcode的测试和Swift,看起来你也可以不使用它。
zvokhttg2#
tl; dr答案
可测试性为单元测试提供了对通常无法从模块/框架外部访问的符号的访问,因此可以为这些组件编写测试。
完整答案
下面是
Testability
在不同上下文中的含义的概述(可能不完整)。斯威夫特
对于Swift,可测试性意味着符号的访问修饰符可以在导入过程中被覆盖。
通常Swift知道以下访问修饰符:
open
:类在当前模块外部可见,可以从当前模块外部重写(除非final
)。open
只能应用于类。public
:符号在当前模块外部可见。如果符号是类,则它可见,但不能从当前模块外部重写。internal
:符号仅在当前模块中可见。顶级符号的默认访问修饰符。fileprivate
:符号仅在当前文件中可见。private
:符号仅在当前封闭范围内可见。如果应用于顶级符号,则行为与fileprivate
完全相同,因为文件本身是封闭范围。启用
Testability
本身不会改变任何东西,但它允许您导入一个模块进行测试。你能做的
这会产生以下效果:
所有
public
或internal
的类都被视为open
。所有其他internal
的符号都被视为public
。fileprivate
或private
的符号保留其访问修饰符。目标语言-C
对于ObjC,可测试性直接改变符号的可见性。
默认情况下,ObjC代码中的所有符号在Swift中都被视为
public
,但类除外,它们在Swift中被视为open
。您可以将符号声明为
__private_extern__
,在这种情况下,它们的行为类似于Swift中的internal
;您也可以将某些符号声明为static
(而不是类或协议),在这种情况下,它们的行为类似于Swift中的fileprivate
。在Xcode构建设置中,您可以启用
Symbols Hidden by Default
,它会自动声明所有符号为__private_extern__
,除非它们是static
。在当前模块之外可见的符号必须使用__attribute__((visibility("default")))
标记为公共符号,例如,您可以使用define:当您启用可测试性时,默认的可见性被重新设置为public,从而覆盖Xcode构建设置
Symbols Hidden by Default
。同时,定义__private_extern__
也被更改,也意味着公共可见性。只有static
符号保持隐藏。-fvisibility=hidden
,默认情况下会强制隐藏所有符号,就像构建设置Symbols Hidden by Default
一样,但是这不能被可测试性覆盖。另外,如果使用__attribute__((visibility("hidden")))
显式标记隐藏符号,这也不能被覆盖。框架
对于框架,可测试性改变了
project
头的可见性。默认情况下,框架头文件有三个可见性级别:
project
:头文件仅在构建框架本身时可用。private
:头在构建框架以及链接到该框架时可用,但在将该框架嵌入到应用程序之前会被删除。public
:标头始终位于框架内,即使框架嵌入到应用程序中。喜欢框架时,
project
标头中的声明不可用。启用可测试性时,project
标头被视为private
标头,因此链接到框架的单元测试能够访问仅在project
标头中声明的符号,并且通常对导入该框架的代码不可见。