实际上,NSAssert有什么意义呢?

时间:2009-09-03 20:33:17

标签: ios iphone cocoa-touch uikit nsassert

我不得不问这个,因为:我唯一认识到的是,如果断言失败,应用程序崩溃了。这就是使用NSAssert的原因吗?或者还有什么好处呢?将NSAssert放在我在代码中做出的任何假设之上是正确的,比如一个函数应该永远不会接收-1作为参数,但可能是-0.9或-1.1?

10 个答案:

答案 0 :(得分:295)

断言是确保一个值应该是它应该是什么。如果断言失败意味着出现问题,那么应用就会退出。使用assert的一个原因是,如果你有一些不起作用的函数,或者如果传递给它的一个参数不完全是某个值(或一系列值),你可以创建一个非常不好的副作用确保这个价值是你所期望的,如果不是,那么事情确实是错的,所以应用程序退出了。断言对于调试/单元测试非常有用,当你提供框架来阻止用户做“邪恶”事情时也是如此。

答案 1 :(得分:20)

我无法真正与NSAssert交谈,但我认为它与C的assert()类似。

assert()用于在代码中强制执行语义合约。这是什么意思,你问?

好吧,就像你说的那样:如果你有一个永远不会收到-1的函数,你可以让assert()强制执行:

void gimme_positive_ints(int i) {
  assert(i > 0);
}

现在你会在错误日志(或STDERR)中看到类似的东西:

Assertion i > 0 failed: file example.c, line 2

因此,它不仅能够安全防范潜在的不良输入,而且还能以有用的标准方式记录它们。

哦,至少在C中,assert()是一个宏,所以你可以在你的发布代码中将assert()重新定义为no-op。我不知道NSAssert是否就是这种情况(或者甚至是assert()),但编译这些检查非常有用。

答案 2 :(得分:17)

除了上面所说的每个人之外,NSAssert()的默认行为(与C的assert()不同)是抛出异常,你可以捕获并处理它。例如,Xcode就是这样做的。

答案 3 :(得分:14)

NSAssert 为您提供的不仅仅是崩溃应用。它告诉您类,方法和断言发生的行。使用NS_BLOCK_ASSERTIONS也可以轻松地停用所有断言。从而使其更适合调试。另一方面,抛出 NSException 只会导致应用崩溃。它也没有告诉异常的位置,也不能简单地禁用它。请参阅下图中的差异。

应用程序崩溃,因为断言也会引发异常,因为NSAssert documentation表示:

  

调用时,断言处理程序会输出一条错误消息   包括方法和类名(或函数名)。然后呢   引发NSInternalInconsistencyException异常。

<强> NSAssert:

Logs after an assertion

<强> NSException:

Logs after an exception

答案 4 :(得分:9)

只是澄清一下,正如有人提到但未完全解释的那样,拥有和使用断言而不仅仅是创建自定义代码(例如,为错误数据做ifs和引发异常)的原因是断言应该禁用生产应用

在开发和调试时,会启用断言以捕获错误。当断言被评估为false时,程序将暂停。 但是,在编译生产时,编译器会省略断言代码并实际上使您的程序运行更快。到那时,希望你已经修复了所有错误。 如果您的程序在生产中仍然存在错误(当断言被禁用并且程序“跳过”断言时),您的程序可能最终会在其他位置崩溃。

来自NSAssert的帮助:“如果定义了预处理器宏NS_BLOCK_ASSERTIONS,则禁用断言。” 因此,只需将宏放在您的分发目标中[仅]。

答案 5 :(得分:6)

NSAssert(及其stdlib等效assert)用于检测开发期间的编程错误。您永远不应该在生产(已发布)应用程序中出现失败的断言。因此,您可能断言您永远不会将负数传递给需要正参数的方法。如果断言在测试期间失败,那么您就有一个错误。但是,如果用户输入了传递的值,则需要对输入进行适当的验证,而不是依赖生产中的断言(可以为禁用NSAssert*的发布版本设置#define。 / p>

答案 6 :(得分:3)

断言通常用于强制执行特定方法或逻辑片段的预期用途。假设您正在编写一种计算两个大于零的整数之和的方法。为了确保方法始终按预期使用,您可能会设置一个测试该条件的断言。

简短回答:他们强制您的代码仅按预期使用。

答案 7 :(得分:3)

值得指出的是,除了运行时检查之外,断言编程是您按合同设计代码时使用的重要工具。

关于断言和合同设计的更多信息可以在下面找到:

Assertion (software development)

Design by contract

Programming With Assertions

Design by Contract, by Example [Paperback]

答案 8 :(得分:2)

要完全回答他的问题,任何类型断言的要点都是为了帮助调试。从源头捕获错误然后在它们导致崩溃时在调试器中捕获它们更有价值。

例如,您可以将值传递给函数,期望值在特定范围内。该函数可以存储该值以供以后使用,并在以后使用应用程序崩溃。在此方案中看到的调用堆栈不会显示错误值的来源。最好抓住坏的价值,因为它会找出谁传递了坏的价值以及为什么。

答案 9 :(得分:-3)

NSAssert使应用与条件匹配时崩溃。如果与条件不匹配,则执行下一个语句。寻找下面的EX:

我只是创建一个应用来测试NSAssert的任务是什么:

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testingFunction:2];
}

-(void)testingFunction: (int)anNum{
    // if anNum < 2 -> the app will crash
    // and the NSLog statement will not execute
    // that mean you cannot see the string: "This statement will execute when anNum < 2"
    // into the log console window of Xcode
    NSAssert(anNum >= 2, @"number you enter less than 2");
    // If anNum >= 2 -> the app will not crash and the below 
    // statement will execute
    NSLog(@"This statement will execute when anNum < 2");
}

进入我的代码,应用程序不会崩溃。测试用例是:

  • anNum&gt; = 2 - &gt;应用程序不会崩溃,您可以看到日志字符串:&#34;此语句将在anNum&lt; 2&#34;进入outPut日志控制台窗口
  • anNum&lt; 2 - &gt;应用程序将崩溃,您无法看到日志字符串:&#34;此语句将在anNum&lt; 2&#34;