断言NSAssert的使用
1. NSAssert
断言(NSAssert)是一个宏,在开发过程中使用NSAssert可以及时发现程序中的问题。
NSAssert声明如下:
#define NSAssert(condition, desc, ...)
- condition:条件表达式。条件成立时,运行后面程序;不成立时,抛出带有
desc描述的异常信息。 - desc:异常描述,通常为
NSString类型对象。用于描述条件表达式不成立的错误信息和参数的占位符。 - ...:
desc字符串中的参数。
假设我们需要判断变量值是否大于5,我们可以用如下代码进行判断。
int i = ;
NSAssert(i>, @"i must bigger than 5");
运行后,控制台没有任何输出。
把变量i的值改为2,如下所示:
int i = ;
NSAssert(i>, @"i must bigger than 5");
运行demo,demo会崩溃。在控制台输出如下信息:
*** Assertion failure in -[ViewController viewDidLoad], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:23
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'i must bigger than 5'
通过控制台输出的信息,可以得到崩溃发生于:ViewController类的viewDidLoad 方法中,该文件位于/Users/ad/Library/Mobile Documents/comappleCloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m,导致崩溃的代码位于第23行,崩溃原因为:i must bigger than 5。
使用NSAssert时可以对输出信息进行传值。
int i = ;
NSAssert1(i>, @"The real value is %i", i);
输出为:
*** Assertion failure in -[ViewController viewDidLoad], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The real value is 2'
NSAssert 用于Objective-C,NSCAssert用于C语言中。
NSAssert1 的desc带有一个参数,NSAssert2 的 desc 带有两个参数,……,NSAssert5 带有五个参数。断言可以带有零至五个参数。
也许你会好奇为什么desc中不使用[NSString stringWithFormat:...]格式,而要有五个NSAssert?因为NSAssert()的实现就是一个宏,因此,要处理异常信息中不同数量参数,就要有多个宏,所以就有了
NSAssert(condition, dest)、NSAssert1(condition, formatDest, arg1)、NSAssert2(condition, formatDest, arg1, arg2)...NSAssert5(...)。
NSAssert和NSLog都可以在控制台输出,但NSAssert输出后程序立即 crash,控制台也会输出程序遇到错误的位置等信息,而NSLog只用于输出信息。
2. NSParameterAssert
如果需要判断传入参数是否符合要求,可以使用NSParameterAssert。
- (NSString *)processItem:(NSUInteger)index {
NSParameterAssert(index<self.myArray.count);
// do something else
}
如果传入参数index大于myArray数组内元素数量,则程序会崩溃。控制它输出如下:
*** Assertion failure in -[ViewController processItem:], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: index<self.myArray.count'
崩溃信息中会告诉你哪一行代码出错了,崩溃原因是什么。
NSParameterAssert用于Objective-C,NSCParameterAssert用于C语言中。
3. 断言默认只存在于debug版
从Xcode 4.2开始,release 版默认关闭了断言。也就是当编译发布版时,任何调用NSAssert的地方都被空行替换。所以,不要在NSAssert内执行任何有效操作。
如果想要在发布版中使用NSAssert,可以在 Build Setting 中的 Enable Foundation Assertions 中修改。

4. NSError
NSError 应该用在不是编程错误所产生的error,如文件未找到一类非致命性错误。你可以把错误信息发送给调用者,调用者会进行处理并继续执行,也可以用警报控制器展现给用户。
总结
对来源于系统内部的可靠数据使用断言,即用断言来处理绝不应该发生的情况。不要对外部不可靠数据(如用户输入、文件、网络读取等)使用断言,即对于外部不可靠数据或预期会发生的情况应当使用错误处理。同时要避免把需要执行的代码放到断言中,断言可以看成可执行的注释。
来源于系统外部的数据都是不可信的,需要严格检查(通常是错误处理)才能放行到系统内部,这相当于一个守卫。而对于系统内部的交互(如调用其他方法),如果每次也都要去处理输入的数据,也就相当于系统没有可信的边界,会让代码变的臃肿。事实上,在系统内部传递给方法正确的参数是调用者的责任,调用者应该确保传递给所调用方法的数据是符合要求的。这样就隔离了不可靠的外部环境和可靠的内部环境,降低复杂度。
但在开发阶段,代码极可能存在缺陷,有可能是处理外部数据的逻辑不周全或调用内部方法的代码存在错误,最终造成调用失败。这个时候,断言就可以发挥作用,用来确诊到底哪一部分问题导致程序出错。在清理了所有缺陷后,内外有别的信用体系就建立起来了。等到发行版的时候,这些断言就没有存在的必要了。
单元测试可能是一个更好的方法,但有些情况下(如复杂的算法过程中),我们希望在代码中执行检查,这时断言将更有效。
参考资料:
作者:pro648
断言NSAssert的使用的更多相关文章
- iOS-----程序异常处理----- 断言NSAssert()和NSParameterAssert区别和用处
NSAssert和assert是断言,主要的差别是assert在断言失败的时候只是简单的终止程序,而NSAssert会报告出错误信息并且打印出来.所以尽管的使用NSAssert,可以不去使用asser ...
- 【转】使用断言NSAssert()调试程序错误
NSAssert()只是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续运行,如果返回假值,则抛出异常,并切可以自定义异 ...
- 使用断言NSAssert()调试程序错误
NSAssert()只是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续运行,如果返回假值,则抛出异常,并切可以自定义异 ...
- 断言--NSAssert
NSAssert()是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续运行,如果返回假值,则抛出异常,并切可以自定义异常 ...
- iOS 10开发NSAssert(断言)的使用
断言(NSAssert)的使用 字数1055 阅读3270 评论3 喜欢30 NSAssert()是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug ...
- 异常:NSException和NSAssert的简单使用
//断言 - (void)NSAssert_Test:(NSString *)string{ NSAssert(string == nil, @"string == kong or nil& ...
- iOS代码规范(OC和Swift)
下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...
- iOS 笔记
1. 使用断言NSAssert()调试程序错误 NSAssert()只是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续 ...
- object-c cocos2d-x 写程序时注意调试的技巧
(1)写程序时最好在类的init函数中显示类名,表明现在在执行哪个类,样例代码 CCLOG(@"cocos2d: Using Director Type:%@", [self cl ...
随机推荐
- 记一次Android studio升级之后的坑
像往常一样打开Android studio,但这次它提示我升级!说是什么为了更好的体验,在好奇心的驱使下,我毅然地点击了“update”按钮.升级之后,编译项目,报出了N多个error,我的心都慌完! ...
- LeetCode 题解之Find Peak Element
1.题目描述 2.题目分析 在数组的首尾各加入INT_MIN ,然后遍历数组. 3.代码 int findPeakElement(vector<int>& nums) { ) ; ...
- KT_登录_流程图
一.需求 关于系统登录功能,需求如下:1.登录需要输入用户名.密码2.如果连续密码输入错误4次,则自动锁定账号5分钟(也就是说5分钟之内不能再登录) 请根据以上需求,画一个登录操作流程图 二.绘图 版 ...
- C#自定义控件的创建
1.创建自定义控件 选择[经典桌面]——[窗体控件库] 2.添加控件,组合成一个新的控件 自定义控件功能:打开一张图片,将图片展示在pictureBox控件中,并将图片的名称.大小.尺寸显示出来 控件 ...
- C# winform 只运行一个应用程序
应用程序只有一个实例,当启动一次时创建实例,当多次启用时激活当前实例. 创建一个单利管理类 using Microsoft.VisualBasic.ApplicationServices; publi ...
- C++发展概述、优缺点及应用领域
个人观点(C++虽功能强大,但是底层还是调用C,C++为了吸引更多的C程序员,功能过于丰富且复杂,一定程度上反而降低了可编程的实用性.但是不可否认C++ 也是一门艺术.) C++是一门以C为基础发展而 ...
- JavaScript大位数相加减
function arrayAdd(number, addNumber) { var numberArr = number.toString().split(''); var addNumberArr ...
- 使用Charles进行网络请求抓包解析
使用Charles进行网络请求抓包解析 0. 懒人的福音(⌐■_■)(破解版下载地址,记得安装java库支持) http://pan.baidu.com/s/1c08ksMW 1. 查看电脑的ip地址 ...
- 解析UIControl
解析UIControl 从下图可以看出,UIControl继承自UIView,添加了响应事件功能. UIButton之所以能响应各种各样的事件是因为继承自UIControl 使用UIControl可以 ...
- Java——并发编程
1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...