前言
对每次运行都会出现的错误通常不会过于苦恼,可以使用断点调试或者
try catch
之类的方式判断并修复它。但是一些偶发(甚至是无数次运行才会出现一次)的错误单靠断点之类的方式是很难排除掉的,为此,引入一个不是很常用的调试工具函数assert
。在实际编码中,为了保证程序正常运行,只有在某些必要条件被满足的情况下才执行特定代码段,这种编程思想叫做 “防错性编程”。
1、断言
在 Swift 语言中可以调用全局的
assert
函数来增加一个断言,这里的全局意思是你可以将断言放在你程序的任何一个地方,程序在执行到assert
时会判断其中的逻辑条件表达式参数是否为true
。- 如果条件判断为
true
,代码运行会继续进行。 - 如果条件判断为
false
,程序将终止。 assert
是单纯地触发断言即停止程序,不会让你有机会将可能出错的设计走过它这一关。
- 如果条件判断为
通常在为程序加入并触发断言后,Xcode 会精确定位到异常代码段,并反馈异常信息等修改 bug 必须的调试信息。
1.1 Assert 的定义
标准的断言格式
assert(condition: Bool, message: String)
condition
判断条件,message
自定义调试信息,断言中的调试信息参数是可选的。
定义
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line) public func assertionFailure(_ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)
系统在断言的源代码中加入了类似
#if NDEBUG
这样的编译字,使其只能用于 debug 期,当你在发布 release 版本或者更新版的时候,编译器会使用一个编译字段将断言无效化,所以当你的产品在提交给用户之后还需要继续收集错误信息时,需使用其他方式。断言函数中用到了
@autoclosure
属性,使用这种属性的参数意味着我们可以在这个参数的位置传入一个表达式,这个表达式会被自动封包成一个闭包,这也正是其字面的意思 “自动闭包”。在assert
函数中它起到的作用也是非常明显的,如果在这里我们使用的是普通的布尔型参数,那么在执行到 assert 函数时,就会先运算条件表达式的值,而使用@autoclosure
属性后,程序会先在assert
函数内判断 debug 期的编译字是否存在,如果存在才会运算条件表达式的值,当然,这时条件表达式已经被自动封装成了一个闭包。
1.2 Assert 的使用
断言使用的几种场景
- 验证参数的合法性。
- 将要使用一个对象,但是不确定其是否已经正确创建。
- 数组或者其他集合类、字典等复杂数据类型下标没有处于安全范围导致可能会越界。
assert
函数的条件表达式参数最好一次只判断一个条件,因为如果判断多个条件,当断言被触发时,往往会无法直观的判断到底是哪一个条件不被满足。使用
// 满足条件 var usedate = -1 assert(usedate <= 0, "超出试用期,不能启动程序!") // 继续执 print("继续执行")
// 不满足条件 // 当 usedate 大于 0 时,程序中断,进入断言函数打印调试信息 usedate = 2 assert(usedate <= 0, "超出试用期,不能启动程序!") // Thread 1: Assertion failed: 超出试用期,不能启动程序!