首先要明白“断言”的意思:
知道了“断言”的意思,就明白了为什么“条件表达式”判断为真时,程序就继续,判断为假时,程序就会抛出异常,退出程序了。
NSAssert()的定义是
#define NSAssert(condition, desc)
condition是条件表达式,值为yes或者no,在OC中规定0为假,非0就为真。
desc为异常描述,为NSString类型。
当condition为yes时程序继续运行;
当condition为no时程序终止并抛出带有desc描述的异常信息。
使用场景:
使用断言主要是要开发和调试阶段,不是用户交互效果。更多的是开发人员之间的沟通手段,比如你设计了一个类,其中的一个实例变量对于输入的值是有有效限制的。为了防止其他开发人员不合理使用这个类,在类的实现文件中放置多个断言,可以起到一个防错功能。
使用举例:
NSInteger age = -1; NSAssert((age > 0 || age == 0), @"年龄不能小于0");
深入了解:
通过制造一个“假”断言,查看日志就会发现,断言NSAssert实际使用的是Foundation框架中的NSAssertionHandler类,用于处理获取假值的断言,而且每个程序线程都拥有其本身的NSAssertionHandler对象,因此,当Foundation框架断言宏的求值为假时,就会将错误情况描述发送给当前线程的NSAssertionHandler对象。该对象会记录错误,并抛出使程序终止的异常(确切地说是一个NSInternallncosistencyException实例)。NSAssertionHandler实例通常不是以编程方式创建的,而是由断言函数创建的。
除了NSAssert断言函数之外,Foundation框架还提供了其他的断言函数:
NSAssert 和 NSCAssert两种“派”别的断言函数有什么区别呢,区别在于 NSAssert 断言宏中含有“self”和“_cmd”,而NSCAssert断言宏中没有用到“self”与“_cmd”:
// NSAssert 断言宏的定义 #if !defined(_NSAssertBody) #define NSAssert(condition, desc, ...) do { __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS if (__builtin_expect(!(condition), 0)) { NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; __assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd object:self file:__assert_file__ lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; } __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS } while(0) #endif
VS
// NSCAssert 断言宏的定义 #if !defined(_NSCAssertBody) #define NSCAssert(condition, desc, ...) do { __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS if (__builtin_expect(!(condition), 0)) { NSString *__assert_fn__ = [NSString stringWithUTF8String:__PRETTY_FUNCTION__]; __assert_fn__ = __assert_fn__ ? __assert_fn__ : @"<Unknown Function>"; NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; __assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; [[NSAssertionHandler currentHandler] handleFailureInFunction:__assert_fn__ file:__assert_file__ lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; } __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS } while(0) #endif