Swift4 基础部分: Error Handling(错误处理)

本文是学习《The Swift Programming Language》整理的相关随笔,基本的语法不作介绍,主要介绍Swift中的一些特性或者与OC差异点。

系列文章:

  • Swift4 基础部分:The Basics
  • Swift4 基础部分:Basic Operators
  • Swift4 基础部分:Strings and Characters
  • Swift4 基础部分:Collection Types
  • Swift4 基础部分:Control Flow
  • Swift4 基础部分:Functions
  • Swift4 基础部分:Closures
  • Swift4 基础部分: Enumerations
  • Swift4 基础部分: Classes and Structures
  • Swift4 基础部分: Properties
  • Swift4 基础部分: Methods
  • Swift4 基础部分: Subscripts
  • Swift4 基础部分: Inheritance
  • Swift4 基础部分: Initialization
  • Swift4 基础部分: Deinitialization
  • Swift4 基础部分: Automatic Reference Counting(自动引用计数)
  • Swift4 基础部分: Optional Chaining(可选链)
Error handling is the process of responding to and 
recovering from error conditions in your program. Swift 
provides first-class support for throwing, catching, 
propagating, and manipulating recoverable errors at 
runtime.
  • 错误处理是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可恢复错误的抛出、捕获、传递和操作的最好的支持。

表示与抛出错误(Representing and Throwing Errors)

例子:

enum VendingMachineError:Error {
    case invalidSelection;
    case insufficientFunds(coinsNeeded: Int);
    case outOfStock;
}

抛出错误:

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

处理错误(Handling Errors)

There are four ways to handle errors in Swift. You can 
propagate the error from a function to the code that calls 
that function, handle the error using a do-catch 
statement, handle the error as an optional value, or 
assert that the error will not occur.
  • Swift 中有4种处理错误的方式。你可以把函数抛出的错误传递给调用此函数的代码、用do-catch语句处理错误、将错误作为可选类型处理、或者断言此错误根本不会发生。

用Throw传递错误(Propagating Errors Using Throwing Functions)

例子

enum VendingMachineError:Error {
    case invalidSelection;
    case insufficientFunds(coinsNeeded: Int);
    case outOfStock;
}

struct Item {
    var price: Int;
    var count: Int;
}

class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 17),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ];
    
    var coinsDeposited = 0;
    
    func vend(itemNamed name:String) throws{
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection;
        }
        
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock;
        }
        
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited);
        }
        
        coinsDeposited -= item.price;
        
        var newItem = item;
        newItem.count -= 1;
        inventory[name] = newItem;
        print("Dispensing \(name)");
    }
}

let favoriteSnacks = [
    "Alice": "Chips",
    "Bob": "Licorice",
    "Eve": "Pretzels",
]

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar";
    try vendingMachine.vend(itemNamed: snackName);
}
  • buyFavoriteSnack函数中将异常抛出。

用Do-Catch处理错误(Handling Errors Using Do-Catch)

接着上述的例子:

var vendingMachine = VendingMachine();
vendingMachine.coinsDeposited = 8;

do {
    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine);
} catch VendingMachineError.invalidSelection {
    print("Invalid Selection.");
} catch VendingMachineError.outOfStock {
    print("Out of Stock.");
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.");
}

执行结果:

Insufficient funds. Please insert an additional 2 coins.

将错误转换成可选值(Converting Errors to Optional Values)

You use try? to handle an error by converting it to an optional value. 
If an error is thrown while evaluating the try? expression, the value 
of the expression is nil.
  • 可以使用try?将错误转成可选值,如果错误被抛出,那么try?执行的表达式结果就是nil

例子

enum CustomError:Error {
    case invalidSelection;
}

func someThrowingFunction(_ num:Int) throws -> Int {
    if num < 0{
        throw CustomError.invalidSelection;
    }
    
    return num;
}

let x = try? someThrowingFunction(-1);
let y: Int?;
let z = try? someThrowingFunction(1);
do {
    y = try someThrowingFunction(-1);
} catch {
    y = nil;
}
print(x);
print(y);
print(z);

执行结果:

nil
nil
Optional(1)

禁止错误传递(Disabling Error Propagation)

Sometimes you know a throwing function or method won’t, in fact, throw an 
error at runtime. On those occasions, you can write try! before the 
expression to disable error propagation and wrap the call in a runtime 
assertion that no error will be thrown. 
  • 如果你确定某个函数不会抛出错误,则使用try!禁止错误传递。

指定清理操作(Specifying Cleanup Actions)

You use a defer statement to execute a set of statements just before code 
execution leaves the current block of code.
  • 可以使用defer语句在执行完代码块中的一系列语句时做一些清理的工作。

例子

func calculateSum(_ nums:inout [Int]) -> Int{
    defer {
        print("defer removeAll");
        nums.removeAll();
    }
    var result:Int = 0;
    for var index in 0...nums.count - 1{
        result += nums[index];
    }
    
    return result;
}

var nums:[Int] = [1,2,3,4,5,6];
print(calculateSum(&nums));
print(nums);

执行结果

defer removeAll
21
[]

你可能感兴趣的:(Swift4 基础部分: Error Handling(错误处理))