swift - 异常处理

Swift 对 Error Handling详解

苹果官方文档解释

跟其它语言一样,Swift的异常处理是在程序抛出异常后的处理逻辑。 Swift提供了一流的异常抛出、捕获和处理的能力。跟Java语言类似, Swift的异常并不是真正的程序崩溃, 而是程序运行的一个逻辑分支;Swift和Java捕获异常的时序也是一样的。当Swift运行时抛出异常后并没有被处理, 那么程序就会崩溃。

在Swift语言中使用Error表示异常, 作用同Java的Exception类或Object-C的NSError类。 苹果建议使用枚举作为异常类型(为什么不推荐用类或者结构体?答案是枚举数据类型本身就是分成若干种情况,很适合做逻辑分支判断条件)。

enum VendingMathineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeed: Int)
    case outOfStack
}

上面声明了枚举类型VendingMathineError,继承于Error。 注意Swift的所有异常类型都继承于Error, 就像Java所有异常类都继承于Exception一样。

类似于Java处理异常的try/catch/finally, Swift提供了try、try?、try!、catch、throw、throws关键字处理异常逻辑,用法跟Java也很像。

如何声明一个可能抛出异常的函数?  在函数参数括号后面添加throws关键字, 跟Java语法有点像;区别是Swift的throws后面不用跟着异常类、而Java的throws后面要有异常类名称。 你只要告诉Swift这个函数可能抛出异常就够了,不需要说明到底是哪种异常,函数体内可以抛出任意类型的异常(肯定是继承于Error)。

func canThrowErrors() throws -> String
func canThrowErrors(type: Int) throws -> String? {
    //函数体写成switch/case更好一些
    if type == 1 {
        throw VendingMathineError.invalidSelection
    }
    if type == 2 {
        throw VendingMathineError.outOfStack
    }
    if type == 3 {
        throw VendingMathineError.insufficientFunds(coinsNeed: 100)
    }
    return "success"
}

上面测试代码是为了测试抛异常逻辑, 函数体写成switch/case更好一些。 从canThrowErrors函数看出,当参数为1、2或3时会抛异常, 语法是throw ... 且程序会跳出函数体,语法同Java。

Swift提供了一种类似于Java try/catch的语法, 是do(函数体内必须有try且该语句可能抛出异常)、catch。

do {

try expression

    statements

} catch pattern 1 {

    statements

} catch pattern 2 where condition {

    statements

}

注意:如果try语句抛出异常则会跳出do代码块,并按顺序逐个catch,当一个catch捕获成功后,后面的catch不再执行。

do {
    var data = try canThrowErrors(type: 3)//执行这个函数 这个函数可能抛出异常

    print("after execute canThrowErrors")
    if data != nil {
        print("Error test data:\(data)")
    }
} catch VendingMathineError.outOfStack {
    print("outOfStack")
} catch VendingMathineError.invalidSelection {
    print("invalidSelection")
} catch {      //类似于Java的catch(Exception ex)
    print("Error")
}
输出:Error

try canThrowsErrors(type: 3)会抛出VendingMathineError.isSufficientFunds(coinsNeed:100),不属于前2个catch类型, 而最后一个catch是捕获所有异常, 所有会执行其函数体。

是不是感觉少了点什么? 对, 少了个类似于Java的finally,后面会介绍。

下面再介绍一下try?和try!的用法。

let x = try? someThrowingFunction()
//与下面的相同
let y: Int?
do{
       y = try someThrowingFunction()
}catch {
    y = nil
}    

try?后面的语句可能会抛出异常, 如果抛出异常则赋值nil给左侧;如果没抛出异常则将返回值赋给左侧;

try!取消异常捕获逻辑,语法有点任性,相当于裸奔, 明知可能抛出异常,但自信这段代码不会抛异常。 try!是try?的补充。你确定后面语句不会抛出异常,但真的抛出异常后程序会崩溃。不建议使用try!,有使用场景推荐使用try?

let tmpX = try? canThrowErrors(type: 1)  //如果抛出异常程序正常运行并赋值nil给左侧, 如果没抛异常则将返回值赋给左侧
//let tmpY = try! canThrowErrors(type: 2)  //你很确定不会抛出异常时这样用,但如果运行时抛异常会导致程序崩溃

Swift使用defer关键字作用同Java的finally, 即使代码块内有break、continue、return或者抛异常,在退出代码块后仍然会执行defer代码块

下面代码只是为了测试,验证函数体内抛出异常时的执行时序, 语法逻辑跟finally一模一样。

func testDefer(_ param: Int) throws -> String {
    print("testDefer begin")
    defer {//抛出异常就执行defer 为抛出异常就最后执行defer
        print("testDefer exit")
    }

// do something... 
    if param == 1 {
        throw VendingMathineError.invalidSelection
    }

    print("testDefer end")

return "testDefer return"

}
//调用函数 该函数抛出异常tmpZ = nil
let tmpZ = try? testDefer(1)
 输出:
testDefer begin
testDefer exit

没有 defer 抛出异常的执行逻辑

func testDeferNormal() {
    print("testDefer begin")
    defer {
        print("testDefer exit")
    }

    print("testDefer end")
}
testDeferNormal()
时间: 2024-08-07 15:30:44

swift - 异常处理的相关文章

swift 中异常的处理方法

swift 中什么时候需要处理异常,在调用系统某个方法的时,该方法最后有一个throws 说明该方法会抛出异常,如果一个方法抛出异常,那么需要对该异常进行处理 swift 异常处理提供了三种方法 方式一: try  ,程序员手动处理异常 do { let regx = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive) } catch { //系统给我们提供了一个临时常量 error //在这里处理异常 pri

Swift 使用 日常笔记

//------------------- var totalPrice: Int = 0 { willSet(newTotalPrice) { //参数使用new+变量名且变量名首地址大写 println("准备将totalPrice值(原值为:\(totalPrice))设为: \(newTotalPrice)") //to do somthing before set. } didSet { if totalPrice > oldValue { println("

Swift开发之异常处理及断言(一)

本篇分两部分: 1.错误和异常处理 2.Swift 中的断言 1.错误和异常处理 在 OC 开发中,我们通常会将 error 置为 nil NSError *error; BOOL success = [data writeToFile: path options: options error: &error]; if(error) { // 错误信息 } 在绝大多数情况下,这个方法并不会发生什么错误,所以我们将 error 直接设置为 nil.但是出错的时候可能就会无从下手进行调试.在 Swi

Swift 2.0 异常处理

WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 iOS 开发当中,我们会面对很多异常处理.在 Cocoa Touch 中我们使用 NSError 来进行异常处理.在新的 Swift 2.0 中,我们可以使用新的 ErrorType protocol. 在 Swift 中, enum 是最好的方法建立属于你自己的异常类型,你只要在你的 enum 中确认新的 ErrorType.

Swift语言里的泛型与异常处理

我感觉泛型挺难,希望对你们有帮助 //一个泛型a,b值交换的列子,可以传入什么类型 func mySwap<T>(inout a: T,inout b: T) { let temp = a a = b b = temp } var a = 111 var b = 222 mySwap(&a, b: &b) //普通整形a,b值交换列子,只能传入整形 func mySwap2(inout a: Int,inout b: Int) { let temp = a a = b b =

swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )

异常处理.类型转换 ( Any and AnyObject ) 1.错误处理 (异常处理) swift 提供第一类错误支持 ,包括在运行时抛出 ,捕获 , 传送和控制可回收错误.在swift中 ,错误用复合 ErrorType 协议的值表示 . Swift枚举把一系列相关的错误组合在一起.同时可以把一些相关的值和错误关联在一起 . 因此 编译器会为实现ErrorType协议的Swift枚举类型自动实现相应的合成 这里看个很简单的小例子. enum WrongName:ErrorType{ cas

Swift中的异常处理

swift中的异常处理 如果在调用系统某一个方法时,该方法最后有一个throws.说明该方法会抛出异常.如果一个方法会抛出异常,那么需要对该异常进行处理 *在swift中提供三种处理异常的方式 方式一:try方式 程序员手动捕捉异常 do { try NSJSONSerialization.JSONObjectWithData(jsonData, options: .MutableContainers) } catch { // error异常的对象 print(error) } 方式二:try

iOS开发——新特性Swift篇&amp;Swift 2.0 异常处理

Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 iOS 开发当中,我们会面对很多异常处理.在 Cocoa Touch 中我们使用 NSError 来进行异常处理.在新的 Swift 2.0 中,我们可以使用新的 ErrorType protocol. 在 Swift 中, enum 是最好的方法建立属于你自己的异常类型,你只要在你的 enum 中确

swift错误和异常处理 --- 南峰子

异常 (exception) 和错误 (error). 在 Objective-C 开发中,异常往往是由程序员的错误导致的 app 无法继续运行,比如我们向一个无法响应某个消息的NSObject 对象发送了这个消息,会得到 NSInvalidArgumentException 的异常,并告诉我们 "unrecognized selector sent to instance":比如我们使用一个超过数组元素数量的下标来试图访问 NSArray 的元素时,会得到NSRangeExcepti