Swift断言`asset` 与 先决条件`precondition`的使用和思考
Posted Jsen_Wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift断言`asset` 与 先决条件`precondition`的使用和思考相关的知识,希望对你有一定的参考价值。
Swift断言asset
与 先决条件precondition
的使用和思考
断言 asset
###定义:
/// - Parameters:
/// - condition: The condition to test. `condition` is only evaluated in
/// playgrounds and `-Onone` builds.
/// - message: A string to print if `condition` is evaluated to `false`. The
/// default is an empty string.
/// - file: The file name to print with `message` if the assertion fails. The
/// default is the file where `assert(_:_:file:line:)` is called.
/// - line: The line number to print along with `message` if the assertion
/// fails. The default is the line number where `assert(_:_:file:line:)`
/// is called.
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
用法:
func call2(_ phone: String)
// 如果phone是11位的,就正常向下执行,如果不是,则阻断流程,打印错误信息
assert(phone.count == 11, "Wrong Phone!")
print("calling" + phone)
call2("18600722414") // 正常执行
call2("186") // 报错,并打印调用栈信息和message
在Assert源码文件中,还有一个与之对应的方法
/// - Parameters:
/// - message: A string to print in a playground or `-Onone` build. The
/// default is an empty string.
/// - file: The file name to print with `message`. The default is the file
/// where `assertionFailure(_:file:line:)` is called.
/// - line: The line number to print along with `message`. The default is the
/// line number where `assertionFailure(_:file:line:)` is called.
@inlinable public func assertionFailure(_ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
这个方法没有判断条件,而是用方法名告诉我们,这就是失败断言直接抛出错误用的,我们可以这样用
func call2(_ phone: String)
if phone.count != 11
assertionFailure("Wrong Phone!")
print("calling" + phone)
call2("123") // 报错,并打印调用栈信息和message
所以这只相当于我们自己动手来实现低错误处罚的时机而已.本质是和assert方法一样的.
先决条件precondition
定义
/// - Parameters:
/// - condition: The condition to test. `condition` is not evaluated in
/// `-Ounchecked` builds.
/// - message: A string to print if `condition` is evaluated to `false` in a
/// playground or `-Onone` build. The default is an empty string.
/// - file: The file name to print with `message` if the precondition fails.
/// The default is the file where `precondition(_:_:file:line:)` is
/// called.
/// - line: The line number to print along with `message` if the assertion
/// fails. The default is the line number where
/// `precondition(_:_:file:line:)` is called.
public func precondition(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
单看定义来说好像和assert基本是一样的.本着存在即合理的角度,我们先不追究区别,先看看用法:
func call(_ phone: String)
// 如果phone的位数为11,则正常执行,若不是则阻断流程,并报错
precondition(phone.count == 11, "Wrong Phone!")
print("calling" + phone)
call("18600722414") // 正常执行
call("123") // // 报错,并打印调用栈信息和message
这么一看,不但作用一样,甚至用法也一样,更甚者,还有一个
@inlinable public func assertionFailure(_ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
方法,对标assertionFailure
方法,并且用法和表现也相同.
问题来了,为什么要弄两个一样功能的方法呢?
显然,这个问题是是不成立的,因为他们倆肯定不一样,
断言Assert
仅在调试环境运行,
先决条件precondition
则在调试环境和生产环境中运行。
这是至关重要的区别,可根据自己的需求而定.
看完源码学到的东西
@autoclosure
实战说话:
假设我们定一个方法,此方法需要传入一个()->T
的闭包作为参数
func test(_ param: () -> String)
print(param())
那么他的调用方式就是
test () -> String in
return "wxs"
这个代码看起来是不是有点乱,尾随闭包的简写,方法名直接跟大括号,即便有多个参数,也会是很难看和难以理解的一种表达方式,所以苹果提供了@autoclosure
经过优化后我们可以写成
// 相较于上边的定义方式,仅仅只加入了一个关键词
func test2(_ param: @autoclosure () -> String)
print(param())
但是调用时的效果却非常不同
test2("wxs")
这样是不是清爽了许多,但是这样需要我们阅读方法的定义才能知道传入的"wxs"
是作为一个闭包传入的,而不是字符串,这里边还可以传入表达式,比如
test2("wxs" + "wxs")
在舒爽的同时,他还不是那么强大,目前只支持()->T
这样的无参数闭包
#file #line #function
这三个标示是为了方便获取代码执行时所在的文件,行数,具体方法的信息.
在assert
和precondition
的方法中我们只见到了#file
#line
,我们先看一下效果
正如图中红框所示,断言报错后,可以获取断言所在的文件和位置信息.
我们再自己写一个使用#function
的demo:
func call3(_ file: StaticString = #file, function: StaticString = #function, line: Int = #line)
print("file:\\(file)\\n function:\\(function)\\n line:\\(line)")
call3()
//print:
file:MyPlayground.playground
function:__lldb_expr_12
line:37
总结
1, asset
只在debug触发,precondition
debug/release都可以触发,可根据业务需要选择,但尽量使用precondition,因为这样可以debug和release表现一致,相信代码严谨度应该会有很高的提升.
2,@autoclosure
是一个高度提高代码整洁性的标示,()->T
类的闭包参数都可使用
3,#file
#line
#function
可在日志类函数提供极大便利.
以上是关于Swift断言`asset` 与 先决条件`precondition`的使用和思考的主要内容,如果未能解决你的问题,请参考以下文章
Swift入门——可选类型(Optionals)与断言(Assert)