iOS-NSParameterAssert总结
一.NSParameterAssert官方解释
Assertions evaluate a condition and, if the condition evaluates to false, call the assertion handler for the current thread, passing it a format string and a variable number of arguments. Each thread has its own assertion handler, which is an object of classNSAssertionHandler.
When invoked, an assertion handler prints an error message that includes method and class names (or the function name). It then raises anNSInternalInconsistencyException exception.
断言评估一个条件,如果条件为 false ,调用当前线程的断点句柄。每一个线程有它自已的断点句柄,它是一个 NSAsserttionHandler 类的对象。当被调用时,断言句柄打印一个错误信息,该条信息中包含了方法名、类名或函数名。然后,它就抛出一个 NSInternalInconsistencyException 异常。
This macro validates a parameter for an Objective-C method. Simply provide the parameter as the condition argument. The macro evaluates the parameter and, if it is false, it logs an error message that includes the parameter and then raises an exception.
这个宏用于确认一个 Objective-C 的方法的有效性。简单提供参数作为条件就行。该宏评估这个参数,如果为 false ,它就打印一个错误日志信息,该信息包含了参数并且抛出一个异常。
Assertions are disabled if the preprocessor macro NS_BLOCK_ASSERTIONS is defined. All assertion macros return void.
如果定义了预处理宏 NS_BLOCK_ASSERTIONS 断言就被禁止了。所有的断点宏都返回 void。
-
断言是从经典的逻辑学中借用过来的概念。在逻辑学中,断言是对已经证明过的命题的陈述。在编程中,断言是指程序员所做出的关于应用程序在它们所声明的地方的一些假设。
-
当用于先验条件和后验条件能力范围内时,断言形成了一种契约,它描述了代码在执行一个方法或函数的开始和结束时的状态的期望。断言也能用于加强运行时的条件,为了当先验条件失败时阻止程序运行。
-
断言与单元测试有些类似,它们都定义了代码将会运行的期望结果。与单元测试不同的是,断言存在于程序本身,并且因此被限定在程序的上下文中。因为单元测试是完全独立的,它们完全有能力通过使用像方法桩和模拟对象等工具隔离并且单独测试特定的行为。开发者应当在应该程序中结合使用合理数量的断言和单元测试来测试和定义应用程序行为。
二.原理
- Objective-C 用一个面向对象的途径混合了 C 语言风格的断言宏定义来注入和处理断言失败。即:
NSAssertionHandler
: - 每个线程拥有它自己的断言处理器,它是 NSAssertionHandler 类的实例对象。当被调用时,一个断言处理器打印一条包含方法和类名(或者函数名)的错误信息。然后它抛出一个
NSInternalInconsistencyException
异常。
三.延伸
基础类库中定义了两套断言宏:
NSAssert / NSCAssert
NSParameterAssert / NSCParameterAssert
基础类库从语义学上和功能性上使断言处理器的 API 在两个方面区别开来。
-
1.第一个区别在于一般断言(NSAssert)和参数化断言(NSParameterAssert)。方法或函数应当在代码最开始处使用 NSParameterAssert / NSCParameterAssert 来强制输入的值满足先验条件,这是一条金科玉律;其他情况下使用 NSAssert / NSCAssert。
-
2.第二个区别在于 C 和 Objective-C 的断言:NSAssert 应当只用于 Objective-C 环境中(即方法实现中),而 NSCAssert 应当只用于 C 环境中(即函数中)
- 当 NSAssert 或 NSParameterAssert 的条件不满足时,断言处理器会调用
-handleFailureInMethod:object:file:lineNumber:description:
方法。 - 当 NSCAssert 或 NSCParameterAssert 的条件不满足时,断言处理器会调用
-handleFailureInFunction:file:lineNumber:description:
方法。
- 当 NSAssert 或 NSParameterAssert 的条件不满足时,断言处理器会调用
值得注意的是,从 Xcode 4.2 开始,发布构建默认关闭了断言,它是通过定义 NS_BLOCK_ASSERTIONS 宏实现的。也就是说,当编译发布版时,任何调用 NSAssert 等的地方都被有效的移除了。
四.断言代码示例
方法一.一般断言,我们可以这么写
if (_menuController == nil || _mainController == nil) {
@throw [NSException exceptionWithName: @"LXDNullInstanceException" reason: @"you can not slide view when one or more of menu view and main view is nil" userInfo: nil];
}
// 如果其中一个条件成立,程序崩溃,报下面的错
// *** Terminating app due to uncaught exception 'LXDNullInstanceException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
方法二:NSAssert
NSAssert(_menuController != nil , @"you can not slide view when one or more of menu view and main view is nil" );
// 方法名 m:118行 报错描述
// *** Assertion failure in -[LXDSlideManager open], /Users/mac/Downloads/LXDSlideManager.m:118
2016-05-29 17:47:53.655
LXDSlideMenuObjectiveC[77358:4074358]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
方法三: NSParameterAssert
NSParameterAssert((_menuController != nil));
// 方法名 m:118行 报错描述
// *** Assertion failure in -[LXDSlideManager open], /Users/mac/Downloads/LXDSlideManager.m:118
2016-05-29 17:47:53.655
LXDSlideMenuObjectiveC[77358:4074358]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
注意条件书写不支持逻辑或语法
// 错误写法,不支持逻辑或语法
NSParameterAssert(_menuController != nil || _mainController != nil);
// 错误写法,不支持逻辑或语法
NSAssert(_menuController != nil || _mainController != nil , @"you can not slide view when one or more of menu view and main view is nil" );