- guard(守护警卫)语句是Swift2之后新添加的关键字,与if语句非常类似,可以在判断一个条件为true的情况下执行某语句,否则终止或跳过执行某语句。它的设计目的是替换复杂的if-else语句嵌套,提高程序的可读性。
- guard语句语法:
guard 条件表达式 else {
跳转语句
}
语句组
Swift中跳转语句跳转语句一般是return
、break
、continue
、throw
,其中return
和throw
可以用于guard。return
是返回,即不在执行后面的语句组;throw
是抛出异常,抛出异常后执行throw
语句,也不再执行后面的语句组。
- 示例1:用if-else嵌套的复杂语句
func if_elseStyleBlog(blog: Blog){
if let blogName = blog.Name{
print("这篇博客名字为:\(blogName)")
if let blogURL = blog.URL{
print("这篇博地址为:\(blogURL)")
if let blogAuthor = blog.Author{
print("这篇博客作者为:\(blogAuthor)")
}else{
print("这篇博客没有作者!")
}
}else{
print("这篇博客没有网址!")
}
}else{
print("这篇博客没有名字!")
}
}
如果使用guard实现同样的功能:
func guardLogStyleBlog(blog:Blog){
guard let blogName = blog.Name else {
print("这篇博客没有名字!")
return
}
print("这篇博客名字为:\(blogName)")
guard let blogURL = blog.URL else {
print("这篇博客没有网址!")
return
}
print("这篇博地址为:\(blogURL)")
guard let blogAuthor = blog.Author else {
print("这篇博客没有作者!")
return
}
print("这篇博客作者为:\(blogAuthor)")
}
由上面可以看出guard可以使一些比较复杂循环判断更简洁,同时guard可以实现可选值绑定。
- 示例2:guard跳转语句使用
throw
来模拟一下数组和角标的关系
//定义一个数组报错的枚举
enum arrayError: Error {
case indexCrossBoard, indexLessZero, arrayIsEmpty
}
//获取数据元素的方法,在参数后面中加入throws关键字标记该方法,在方法体内部使用throw抛出具体的错误类型。
func getObjByIndex(index:Int) throws -> Int {
let array = [1,2,3,4,5]
//index必须小于array的cont
guard index < array.count else { throw arrayError.indexCrossBoard }
//index必须大于等于0
guard index >= 0 else { throw arrayError.indexLessZero }
//数组不能为空
guard array.count > 0 else { throw arrayError.arrayIsEmpty }
print(array[index])
return array[index]
}
//调用方法,有抛出就一定有接收,所以方法在被调用时会被强制加上`do catch try`关键字,不然编译器会报错。
do {
let _:Int = try getObjByIndex(index: 5)
} catch arrayError.indexCrossBoard {
print("数组脚标越界")
} catch arrayError.indexLessZero {
print("数组角标不能为负数")
} catch arrayError.arrayIsEmpty {
print("/数组不能为空")
} catch {
}
结果为数组脚标越界
,当一个方法体被throws关键字标记后的方法代表它可能会向外抛出错误,这个错误可以是自定义的,可以取自上面自定义的枚举。
上面抛出异常的写法虽然看着比较简单明了,但是不叫臃肿,每次调用都要写do catch try
,我们可以封装成一个回调的闭包。
//定义一个闭包
typealias ArrayErrorCallback = () throws -> Bool
//定义方法
func checkObjectById(index:Int, errorBlock:@escaping (_ inner:ArrayErrorCallback) -> Void) {
let array = [1,2,3,4,5]
if index < array.count && index >= 0 {
// throw error
errorBlock({ throw arrayError.indexCrossBoard })
}
if index < 0 {
errorBlock({ throw arrayError.indexLessZero })
}
if array.count == 0 {
errorBlock({ throw arrayError.arrayIsEmpty })
}
// return value
errorBlock({return true})
}
//调用方法
checkObjectById(index:-5) { (inner: ArrayErrorCallback) -> Void in
do {
let success = try inner()
print(success)
} catch {
print(error)
}
}
用法差不多,只是把throws标记在闭包上。更适合异步操作的场景。