NSAssert 是c语言的一个宏定义。 看一下具体定义:
#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)
具体使用:
NSAssert(condition, desc);
当condition为空的时候,中断程序,打印后面的desc。
所以一般condition一般放的是一个对象或者 对象 != nil。后面的desc一般放字符串。
注意condition不支持逻辑或语法
//错误写法
NSAssert(a != nil || b != nil, @"dddd");
NSAssert、assert和NSParameterAssert的区别:
assert 和 NSParameterAssert都只有一个参数,即condition,不会有后面的错误描述。
从 Xcode 4.2 开始,发布构建默认关闭了断言,它是通过定义 NS_BLOCK_ASSERTIONS 宏实现的。也就是说,当编译发布版时,任何调用 NSAssert 等的地方都被有效的移除了。
自定义NSAssertionHandler
NSAssertionHandler实例是当前线程自动创建的,用于处理错误断言。当使用NSAssert发生错误的时候的时候会向NSAssertionHandler发送错误的字符串。我们可以通过自定义NSAssertionHandler重写处理方法,从而避免程序崩溃。
@implementation CustomAssertHandler
//处理Objective-C的断言
- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,... {
NSLog(@"NSAssert Failure: Method %@ for object %@ in %@#%li", NSStringFromSelector(selector), object, fileName, (long)line);
}
同时需要在线程中将自定义的NSAssertionHandler替换。
//自己定义的NSAssertionHandler
NSAssertionHandler *myHandler = [[CustomAssertHandler alloc] init];
//给当前的线程
[[[NSThread currentThread] threadDictionary] setValue:myHandler forKey:NSAssertionHandlerKey];
到这,当NSAssert检测当为空的对象时,就会调用handleFailureInMethod,此时程序不会崩溃。