1.一般处理错误步骤:
1.使用 Error 建立异常类型
例:
//处理更细分的错误情况,错误类型须遵从Error协议
enum DogError : Error{
case NameInvalidError
case AgeInvalidError
case NameLengthError
}
2.使用 throws 来声明异常,用 throw 来抛出异常
一个函数可以加上throws关键字,表示可以处理错误. 这个函数的调用者可以捕获(catch)这个错误并进行应对.
如何抛出异常:
1.在抛出异常之前,我们需要在函数或方法的返回箭头 -> 前使用 throws 来标明将会抛出异常
例:
//有返回值时
func myMethodRetrunString() throws -> String
//无返回值时
func myMethodRetrunNothing() throws
2.声明之后, 我们需要在函数或者方法里扔出异常,很简单使用throw 就可以了
3.使用 do-catch 机制来获取和处理throw抛出的异常
用 Do-Catch 处理错误:
可以使用一个do-catch语句运行一段闭包代码来处理错误。如果在do子句中的代码抛出了一个错误,这个错误会与catch子句做匹配,从而决定哪条子句能处理它。
下面是do-catch语句的一般形式:
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
}
4.当你调用可以抛出错误的函数,须在前面加上try关键字.
do{
//当你调用可以抛出错误的函数,须在前面加上try关键字.
try str = myDog.printDogMessage(dog: myDog)
}
catch {
switch (error){
case DogError.NameInvalidError: print("dog的名字无效错误")
case DogError.NameLengthError : print("dog的名字长度错误")
case DogError.AgeInvalidError : print("dog的年龄设置不合法")
default:print("Main:捕获到dog其他错误")
}
}
Demo:
//处理更细分的错误情况,错误类型须遵从Error协议
enum DogError : Error{
case NameInvalidError
case AgeInvalidError
case NameLengthError
}
import UIKit
//NSObject需添加UIKit
class Dog: NSObject {
var name : String!
var age : Int!
init(name:String,age:Int){
self.name = name
self.age = age
}
//一个函数可以加上throws关键字,表示可以处理错误. 这个函数的调用者可以捕获(catch)这个错误并进行应对.
//使用 throws 来声明异常,用 throw 来抛出异常
func printDogMessage(dog:Dog) throws -> String{
print("Dog-Class:开始检查名字是否无效")
//guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句.
guard let name : String = dog.name else{
throw DogError.NameInvalidError
}
print("Dog-Class:开始检查名字长度是否无效")
if name.characters.count < 3{
throw DogError.NameLengthError
}
print("Dog-Class:开始检查年龄是否无效")
if age < 0 || age > 20{
throw DogError.AgeInvalidError
}
print("Dog-Class:返回信息")
return "dog的信息为" + dog.name + "\(dog.age)"
}
}
调用错误处理方法的代码:
方法1:直接do-catch调用
let myDog = Dog(name: "小白",age: 18)
var str : String!
do{
//当你调用可以抛出错误的函数,须在前面加上try关键字.
try str = myDog.printDogMessage(dog: myDog)
}
catch {
switch (error){
case DogError.NameInvalidError: print("dog的名字无效错误")
case DogError.NameLengthError : print("dog的名字长度错误")
case DogError.AgeInvalidError : print("dog的年龄设置不合法")
default:print("Main:捕获到dog其他错误")
}
}
print("Main:最后输出为\(str)")
/*打印如下: Dog-Class:开始检查名字是否无效 Dog-Class:开始检查名字长度是否无效 dog的名字长度错误 Main:最后输出为nil */
方法2:包装do-catch方法后调用
func testDogError(testdog:Dog){
do{
var teststr : String!
try teststr = testdog.printDogMessage(dog: testdog)
//只有正确时才会有返回值打印
print("正确:\(teststr)")
}
catch {
switch (error){
case DogError.NameInvalidError: print("dog的名字无效错误")
case DogError.NameLengthError : print("dog的名字长度错误")
case DogError.AgeInvalidError : print("dog的年龄设置不合法")
default:print("Main:捕获到dog其他错误")
}
}
}
let myDog1 = Dog(name: "小白兔",age: 30)
testDogError(testdog: myDog1)
let myDog2 = Dog(name: "小白狗",age: 18)
testDogError(testdog: myDog2)
/*打印如下: Dog-Class:开始检查名字是否无效 Dog-Class:开始检查名字长度是否无效 Dog-Class:开始检查年龄是否无效 dog的年龄设置不合法 Dog-Class:开始检查名字是否无效 Dog-Class:开始检查名字长度是否无效 Dog-Class:开始检查年龄是否无效 Dog-Class:返回信息 正确:Optional("dog的信息为小白狗Optional(18)") */
2. 不用do-catch的简便调用 try! 与 try?
try?与try! 方式的简便调用不用写do{}catch{}
1. try! 的使用
try! :这种写法适用确定一定会成功的情况,需要确定一定不会出现有异常抛出的情况,这种写法建议不要用或者少用。
let myDog4 = Dog(name: "小白狗",age: 18)
//try! ...这种写法适用确定一定会成功的情况,需要确定一定不会出现有异常抛出的情况,这种写法建议不要用或者少用。
testresult = try! myDog4.printDogMessage(dog: myDog4) //"dog的信息为小白狗Optional(18)"
if (testresult != nil){
print("完成设置!")
} else {
print("条件不符,无法设置")
}
//输出:"完成设置!\n"
2. try? 的使用
try?:与上面的写法类似,不同的地方在于,当有错误或者异常时不会抛出异常,而是给结果反回nil,这种写法适用于不需要处理异常的情况,成功就返回结果,失败返回nil,忽略异常信息。
let myDog3 = Dog(name: "小白",age: 18)
//try? ...与上面的写法类似,不同的地方在于,当有错误或者异常时不会抛出异常,而是给结果反回nil,这种写法适用于不需要处理异常的情况,成功就返回结果,失败返回nil,忽略异常信息。
var testresult = try? myDog3.printDogMessage(dog: myDog3) //nil
if (testresult != nil){
print("完成设置!")
} else {
print("条件不符,无法设置")
}
//输出:"条件不符,无法设置\n"
3. 清理收尾 defer
//在你的代码块就要结束前。如果你使用了 defer。 在其之中的代码就会运行。等于说,给了你最后的机会来进行一些处理。
//注意,如果你有多个defer 语句,他们在执行的顺序会和栈一样,最后一个进,第一个出。
func pk() {
//defer:结束前运行
defer {
print("结束")
}
print("开始")
print("进行")
}
pk()
/*输出: 开始 进行 结束 */