【发布时间】:2012-08-15 20:04:03
【问题描述】:
我想禁用在构建我们的发布 iOS 二进制文件时发生在我们的代码行中的 NSAssert 调用,然后我想确认它们已被禁用,因为我是超级偏执狂。如何确认它们已被禁用?
为了在我们的发布版本中禁用 NSAssert 调用,我已将 NS_BLOCK_ASSERTIONS=1(来自 here)常量添加到我正在使用 xcodebuild 进行的命令行发布版本中,以便在整个应用程序的构建中阻止 NSAssert,包括它使用的所有静态库的构建。对于数十个静态库,尝试验证在每个库的项目文件中设置此标志的维护量太大,因此首选这种全局方法。它看起来像这样:
xcodebuild -target MyApp -configuration MyReleaseConfig -DNS_BLOCK_ASSERTIONS=1 build
然后确认我们对 NSAssert 的调用确实已被阻止,这就是我正在尝试的方法,也是我寻求建议的地方:我将符号表从生成的二进制文件中转储出来,并寻找 NSAssert 的实际方法宏调用,如下所示:
# Use 'nm' tool to dump symboltable into txt file
/Applications/Xcode.app/Contents/Developer/usr/bin/nm MyApp.app/MyApp > MyApp.symbols.txt
# Search symbols for NSAssertionHandler:
grep "NSAssertionHandler" ./MyApp.symbols.txt
# Output results:
RESULT=$?
if [ $RESULT -eq 0 ]
then
echo -e "** ASSERTION CHECKER FAILED: FOUND 1 OR MORE NSASSERT CALLS IN RELEASE BINARY **"
else
echo -e "** ASSERTION CHECKER SUCCEEDED: NO NSASSERT CALLS IN RELEASE BINARY **"
fi
问题是我仍然看到 NSAssertionHandler 出现在符号中:
U _OBJC_CLASS_$_NSAssertionHandler
我怀疑我使用 nm 不正确;或者,也许这个符号出现是因为我们正在链接使用 NSAsserts 的第三方库,或者 iOS API 本身使用 NSAsserts,从而混淆了我的验证步骤。我希望在我们的发布版本中阻止我们对 NSAssert 的所有代码调用——我如何验证是否是这种情况?任何建议将不胜感激!
【问题讨论】:
-
在我的发布配置中,我使用“NS_BLOCK_ASSERTIONS=1 NDEBUG”,所以即使你使用 xcodeBuild,你也会选择它们。您还想添加 NDEBUG,因为它会禁用“assert()”(我使用的东西比 NSAssert 多,因为它更容易输入)。
-
自从两周前发布这个问题以来,我还没有发现任何方法来确认构建确实已经剥离了断言。所以我将继续在我们的正式构建过程中实现命令行设置(
-DNS_BLOCK_ASSERTIONS=1和-NDEBUG),并且相信它可以工作,因为这是我能做到的最好的做。但如果有人有想法,我仍然很想听听他们的意见。谢谢。 -
这很容易做到。在 applicationDidLoad 中,然后添加 #ifdef DEBUG\nassert*0);\n#else\nNSLog(@"Asserts are ON");\nendif.你可以用 #if NS_BLOCK_ASSERTIONS == 1\nNSAssert(0, @"Gotcha");\n... 做同样的事情
-
applicationDidLoad技巧是检测NSAssert和assert是否存在调用单体应用程序的好主意,谢谢。我的情况需要从链接到我的几十个静态库的应用程序中剥离这些调用,因此我需要确保主应用程序及其库都没有这些调用。这就是为什么我在命令行构建级别对此进行攻击,因为命令行构建参数会覆盖主要应用程序设置,以及十几个静态库的设置(以及偷偷摸摸的 .xcconfig 覆盖等)。 -
如果我错了,请纠正我,但 NS_BLOCK_ASSERTIONS 不是预处理器宏,因此它只适用于您的源文件,而不适用于任何已经编译的静态库?除非它修改了断言处理程序以便断言保留在代码中但不抛出异常?