相对于NSLog函数的无条件输出,即程序运行到该处就会输出结果;使用NSAssert宏可以实现有条件输出结果。
NSAssert是foundation.framework中定义的一个宏:#define NSAssert(condition, desc, ...)第一个参数为一个条件判断,如果为假,则抛出异常,显示第二个参数所描述的信息。
例如:NSAssert(2>=3, @"2>=3 is false!");在debug模式下运行,会终止程序,并抛出如下异常:2013-04-24 09:24:16.618 TestAssertion[825:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '2>=3 is false!'。在release模式下运行,不终止程序不抛出异常,这样做很方便调试程序。当在真机中时,会自动忽略。调试cocoa程序在程序出错时,不会马上停止。使用宏NSAssert可以让程序出错时马上抛出异常。在debug情况下,所有NSAssert都会被执行。在release下不希望NSAssert被执行,我们通常在release种将断言设置成禁用。设置方法:在targets种选择build,选择release。在gcc preprocessing下增加Preprocessor Macros 值为 NS_BLOCK_ASSERTIONS.
使用assert也是有缺点的,频繁的调用会极大的影响程序的性能,增加额外的开销。 在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:
#include <stdio.h> #define NDEBUG #include <assert.h>
用法总结与注意事项:
1)在函数开始处检验传入参数的合法性,如:
int resetBufferSize(int nNewSize) { //功能:改变缓冲区大小, //参数:nNewSize 缓冲区新长度 //返回值:缓冲区当前长度 //说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区 assert(nNewSize >= 0); assert(nNewSize <= MAX_BUFFER_SIZE); ... } 2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败 不好: assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好: assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误: assert(i++ < 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
正确: assert(i < 100)i++;
4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
5)有的地方,assert不能代替条件过滤
有时我们可能会用到NSassert1和NSassert2,其说明如下:
NSAssert1 is a variant that takes an additional argument and inserts it into the format string provided, like so:NSAssert1((a == b), @"Error message: %@", someErrorString);
NSAssert2(0, @"%@%@", @"foo", @"bar");
NSAssert2是后面带2个显示参数,依次类推。