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

156 iphone cocoa-touch uikit ios nsassert

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

Dan*_*iel 300

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

  • >你应该拿出NSAssert来发布.这是值得商榷的.我总是在启用断言的情况下发布我的应用程序,这是许多软件的标准做法,Apple就是这样做的.一旦程序检测到异常状态,您就应该崩溃.您可以获得错误发生位置的堆栈跟踪,而如果禁用断言,最终可能会破坏内存和/或用户数据,并且问题将很难调试. (127认同)
  • 请注意,XCode 4在发布配置中默认定义了NS_BLOCK_ASSERTIONS.我想如果你不改变你发布的代码将不包含NSAssert:s. (18认同)
  • 如果我理解正确,离开它们的重点是什么(在发布版本上)?为什么不用if语句替换NSAssert,如果(发生可怕的事情),然后通知用户(或做一些*your*control下的事情),而不仅仅是退出/崩溃并让用户想知道发生了什么......或者我错过了什么? (16认同)
  • 在正常情况下完全不应该发生的每个特殊情况的路径都是浪费开发人员的时间.这涉及考虑适当的方式来告知用户他们中的每一个和/或使应用程序足够健壮以在其发生之后以预期的方式继续.更实用的方法是崩溃应用程序并修复崩溃报告中发现的错误并发布新版本.话虽如此,确保在任何此类情况下都不会丢失数据非常重要.尽管如此,必须确保这一点,但这项工作要少得多. (11认同)
  • 你应该拿出NSAssert来发布.有一个编译时标志来做到这一点. (9认同)
  • 完善.明天要投票.达到每日投票限额.是否可以在发布产品中保持断言?或者我必须在构建发布时从我的代码中删除它们吗? (2认同)
  • 您的应用应该*永远*不会因为意外数据而崩溃。如果你懒得写断言,你可以写一个 if 语句来优雅地处理这种情况。我不确定 Apple 应用程序代码,我从未见过。SDK 代码是不同的 - 他们在那里断言是合适的,因为 SDK 无法预测开发人员希望如何处理他们的应用程序中的案例。作为开发人员,任何实现都可以设计为安全的故障转移,并且应该如此。 (2认同)

Man*_*lla 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()),但编译这些检查非常有用.

  • 是的,NSAssert也是一个宏. (2认同)

Jen*_*ton 17

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


Abd*_*Ali 16

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

应用程序崩溃,因为断言也会引发异常,因为NSAssert文档指出:

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

NSAssert:

断言后记录

NSException:

异常后记录


Oha*_*ick 9

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

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

从NSAssert的帮助:"如果定义了预处理器宏NS_BLOCK_ASSERTIONS,则禁用断言." 所以,只需将宏放在您的分发目标中[仅].


Bar*_*ark 6

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

  • +1因为你的答案对我来说最有意义!使用NSAssert更有意义,如果它用于开发使用,而不是在发布之后.输入不允许的值的用户之后应该是UI错误,而不是NSAssert崩溃应用程序.雾已经清除了! (2认同)