swift3新路程(11)错误处理(Error Handling)

我们在Java等其他语言之都知道有错误处理 基本上都是 try和catch配对的

那么在swift中同样也有

我们首先可以定义一下自己的错误类型如下面

enum MyErrors:Error {
    case NOT_NUMBERIC
    case NO_NAME
    case OUT_OF_RANGE
    
}
对于异常的抛出,同样是使用throw关键字,我们使用throws来标记某个函数有异常抛出

我们来定义一个函数,用来做异常抛出

func testMyErrors(name:String,objects:[NSObject],index:Int ) throws -> Void {
    if name.isEmpty {
        throw MyErrors.NO_NAME
    }
    if objects.count < index {
        throw MyErrors.OUT_OF_RANGE
    }
    for object in objects {
        if !(object is Int) {
            throw MyErrors.NOT_NUMBERIC
        }
    }
    print("Name is \(name)")
}


然后我们如何捕获异常并做处理呢?

do {
    let objs:[NSObject] = [3 as NSObject,4 as NSObject]
    try testMyErrors(name: "", objects:objs, index: 1)
} catch MyErrors.NO_NAME {
    print("名称为空")
}
我们看到使用的是 do 和 catch 当然还有try 不过try的位置跟我们所熟悉的Java代码的位置有所不同

我们这里讲name设置为空,那么就会抛出一个MyErrors.NO_NAME的异常,我们在catch中可以捕获,并做相应的处理,那么这里将会输出”名字为空“的信息

当然这是我们已经知道的可能发生的异常,我们可以精确地捕捉到,我们都知道Java中的异常处理一般是按照从小到大的范围进行网络的,最后就是最大的异常类型Exception

在swift中同样也可以,上面我们知道了名字可能为空,其他的具体还会发生什么,我们可能不太清楚,我们就可以使用下面的处理

do {
    let objs:[NSObject] = ["Ryoma" as NSObject,4 as NSObject]
    try testMyErrors(name: "Ryoma", objects:objs, index: 1)
} catch MyErrors.NO_NAME {
    print("名称为空")
} catch let myError as MyErrors {
    print(myError)
} catch {
    print(error)
}
这里我们看到名字不会出现问题了,但是数组内的第一项不是Int类型的,这时肯定会出异常,我们的MyErrors.NO_NAME这个类型肯定捕获不到的,但是我们在后面定一个myError是MyErrors的类型,也就是如果发生的错误是MyErrors类型的,几遍我们上面的catch没有捕获到,我们的myError也可以捕获到,并做相应的处理。

如果说在上面的业务代码块中出现了我们无法预测的错误,不在我们所能想到的错误类型中,那也不怕,我们最后的catch会帮我们捕获到,并做处理。

最后的catch中如果我们没有对Error的名字做出什么定义的话(myError就是我们自己定义的名字)话,会有一个默认的错误类型名就是error


当然除了上面的这些错误处理同样还有一种处理,我们使用 try?形式

我们还是使用上面的异常

let objs:[NSObject] = ["Ryoma" as NSObject,4 as NSObject]
try testMyErrors(name: "Ryoma", objects:objs, index: 1)

这样写的话因为没有catch,是无法捕获异常的,程序肯定是崩溃的

let objs:[NSObject] = ["Ryoma" as NSObject,4 as NSObject]
try? testMyErrors(name: "Ryoma", objects:objs, index: 1)

如果我们这样写了,使用了try?的话程序就会ok的结束,如果try?后面的执行抛出了异常,那么这个异常会被忽略,如果try?的后面是具有返回值的表达式,那么这个表达式的值就是nil,如果没有异常发生,那么这个表达式的值就会被转成一个可选的值(有可能有也有可能为nil)

关于异常处理还有一个点就是defer,我个人感觉他就像是Java中的finally,就是不管这个处理中有没有异常发生,都要执行的,我们可以这里面做一些自己需要的处理,而且如果我们在一个处理中写有多个defer的话,他是按照先进后出的原则执行的

func say(){
    do {
        let objs:[NSObject] = ["Ryoma" as NSObject,4 as NSObject]
        try testMyErrors(name: "Ryoma", objects:objs, index: 1)
    } catch MyErrors.NO_NAME {
        print("名称为空")
    } catch let myError as MyErrors {
        print(myError)
    } catch {
        print(error)
    }
    defer {
        print("finally will be executed even if there's an error")
    }
    defer {
        print("defer2")
    }
    defer {
        print("defer3")
    }
}
say()

输出

NOT_NUMBERIC

defer3

defer2

finally will be executed even if there's an error





你可能感兴趣的:(Swift)