如何在发布版本中确定NSAssert是否已禁用?

47

我经常在iOS代码中看到"assert",我谷歌了一下,知道它是断言真或假。

我想知道它是否会在发布模式下自动禁用?


3
说实话,这个设计有些疯狂,因为默认情况下发布版本中的断言并没有被关闭。这与我所知道的其他C编译器完全相反。 - Seva Alekseyev
2
@SevaAlekseyev 同意,当断言在发布版本中仍然出现时,我们感到震惊。这是完全不同寻常的。我们的理念是“在开发中快速失败,在生产中坚韧不拔”。 - Chris Hatton
7个回答

51

更新: 已验证此方法也适用于Xcode 8。

在 Xcode 7 中,进入项目构建设置并在搜索栏中搜索 "Assert"。这将显示“Apple LLVM 7.0 - Preprocessing”部分。有一个名为“启用基础框架断言”的设置。

我已成功从那里启用/禁用了 NSAssert。

输入图像描述


2
ENABLE_NS_ASSERTIONS = NO; 标志添加到应用程序的 AppName.xcodeproj/project.pbxproj 文件中。 - computingfreak

47

使用NSAssert()及其相关方法。

在项目中为你的发布配置定义NS_BLOCK_ASSERTIONS

Xcode 4模板会在发布配置中禁用NSAsserts。它会添加

-DNS_BLOCK_ASSERTIONS=1

针对“Release”配置,将代码中的C标志更改为“其他 C 标志”。

根据文档:

如果预处理器宏 NS_BLOCK_ASSERTIONS 被定义,则禁用断言。

NSAssert 宏评估条件并作为断言处理程序的前端。

每个线程都有自己的断言处理程序,它是NSAssertionHandler类的对象。当调用时,断言处理程序会打印包括方法和类名(或函数名)在内的错误消息。然后,它会引发一个 NSInternalInconsistencyException 异常。如果条件求值为 NO,则该宏会在当前线程的断言处理程序上调用handleFailureInMethod:object:file:lineNumber:description:,并将 desc 作为描述字符串传递。

此宏仅应在 Objective-C 方法中使用。


35

我在这里提供一个元回答:

@CocoaFu 和 @dasblinkenlight 都是正确的。 NS_BLOCK_ASSERTIONS 关闭了 NSAssert()NDEBUG 关闭了 assert()。如果你同时使用两者,则两者都需要。


阅读@Rob的iOS 5编程:获取它,阅读它,在iOS 5中更好地编程。 - zaph
很遗憾,您在这两个单词的总结中拼错了一个。 - Ant
1
已注意并修复。NSDEBUG->NDEBUG。 - Rob Napier
1
NDEBUG=1 应该被添加到预处理器宏部分,而不是其他C标志。 - nalexn
2
@NAlexN 你可以将它传递给其他的C标志,但是它需要采用-DNDEBUG=1的形式,使用-D来指定宏定义。 - Kekoa

8
作为Zaph所说,-DNS_BLOCK_ASSERTIONS=1在发布时被设置。但是,如果您想要检查这一点,请首先观察文档,了解NSAssert由宏NS_BLOCK_ASSERTIONS禁用。然后将其添加到构建中并观察它是否编译通过。
#ifdef NS_BLOCK_ASSERTIONS
#error Error - NS_BLOCK_ASSERTIONS is defined
#endif

然后将方案更改为发布(cmd-shift-<)

enter image description here

然后观察构建失败。因此,定义了NS_BLOCK_ASSERTIONS,意味着NSAssert被禁用。


5

当定义了NDEBUG时,断言将被有条件地编译出代码。如果在对应的构建设置部分中定义NDEBUG=1,则无论是发布模式还是调试模式,都会停用代码中的断言。


3
这是我在main()函数开头的工作内容:
#if defined(NDEBUG)
{
  // The assertion code below should be compiled out of existence in a release
  // build.  Log an error and abort the program if it is not.
  bool ok = true;
  NSCAssert(ok = false, @"NS assertions should be disabled but are not");
  if (!ok)
  {
    NSLog(@"Detected release build but NS_BLOCK_ASSERTIONS is not defined");
    return -1;
  }
}
#endif

请注意,由于main()是C函数而不是Objective-C函数,因此上面使用的是NSCAssert而不是NSAssert。(NSAssert期望self是有效的。)

1

从 Xcode 6 开始,设置是 ENABLE_NS_ASSERTIONS,默认情况下对于调试配置设置为 1,而对于发布配置设置为 0

你可以通过在命令行中传递 ENABLE_NS_ASSERTIONS=1 参数来选择在发布版本中采用它,我在运行检查断言条件的单元测试时会这样做,但否则应该关闭 DEBUG 标志。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接