• swift学习笔记之-错误处理


    //错误处理

    import UIKit

    /*错误处理(Error Handling):响应错误以及从错误中恢复的过程

    在 Swift 中,错误用符合ErrorType协议的类型的值来表示。这个空协议表明该类型可以用于错误处理,Swift 的枚举类型尤为适合构建一组相关的错误状态,枚举的关联值还可以提供错误状态的额外信息

    抛出错误使用throw关键字,如:throw VendingMachineError.InsufficientFunds(coinsNeeded: 5)

    处理错误:

        1.某个错误被抛出时,附近的某部分代码必须负责处理这个错误,例如纠正这个问题、尝试另外一种方式、或是向用户报告错误

        2.Swift 中有4种处理错误的方式。你可以把函数抛出的错误传递给调用此函数的代码、用do-catch语句处理错误、将错误作为可选类型处理、或者断言此错误根本不会发生

        3.为了标识出会抛出错误的地方,在调用一个能抛出错误的函数、方法或者构造器之前,加上try关键字,或者try?或try!这种变体

        4.用 Do-Catch 处理错误:

            a.如果在do子句中的代码抛出了一个错误,这个错误会与catch子句做匹配,从而决定哪条子句能处理它。

            b.如果一条catch子句没有指定匹配模式,那么这条子句可以匹配任何错误,并且把错误绑定到一个名字为error的局部常量

            c.catch子句不必将do子句中的代码所抛出的每一个可能的错误都作处理,如果所有catch子句都未处理错误,错误就会传递到周围的作用域,但错误最终都要被处理。

            do {

                try ...

            }catch ... {

                ...

            }catch ... {

                ...

            }

    用 throws 函数传递错误:

        1.为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字。一个标有throws关键字的函数被称作throws函数。如果这个函数指明了返回值类型,throws关键词需要写在箭头(->)的前面。如:func canThrowErrors() throws -> String

        2.一个 throws 函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。

        3.只有 throws 函数可以传递错误。任何未声明为throws的函数内部抛出的错误只能在函数内部处理!

    将错误转换成可选值:

        1.可以使用try?通过将错误转换成一个可选值来处理错误。如果在评估try?表达式时一个错误被抛出,那么表达式的值就是nil

            func fetchData() -> Data? {

                if let data = try? fetchDataFromDisk() { 

                    return data 

                }

                if let data = try? fetchDataFromServer() { 

                    return data 

                }

                return nil

            }

    禁用错误传递:在表达式前面写try!来禁用错误传递,这会把调用包装在一个断言不会有错误抛出的运行时断言中。如果实际上抛出了错误,你会得到一个运行时错误。

           如: let photo = try! loadImage("./Resources/John Appleseed.jpg")  虽然loadImage函数为throws函数,但此处通过给定的参数调用时不会抛出错误,所以用禁用错误传递try!

    指定清理操作:

        1.使用defer语句在即将离开当前代码块时执行一系列语句,该语句让你能执行一些必要的清理工作,不管是以何种方式离开当前代码块的——无论是由于抛出错误而离开,还是由于诸如return或者break的语句,

        2.defer语句将代码的执行延迟到当前的作用域退出之前

        3.该语句由defer关键字和要被延迟执行的语句组成。延迟执行的语句不能包含任何控制转移语句,例如break或是return语句,或是抛出一个错误。延迟执行的操作会按照它们被指定时的顺序的相反顺序执行

        func processFile(filename: String) throws {

            if exists(filename) {

                let file = open(filename)

                defer {

                    close(file)     //defer内的语句将被延迟执行,执行多语句时反顺序执行

                }

                while let line = try file.readline() {

                    // 处理文件代码

                }

                //defer内的 close(file) 在这里才会被调用,即作用域的最后。

            }

        }

    */

    //===================用枚举定义错误类型信息=====

    enum VendingMachineError: ErrorType {

        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: 7),

            "Chips": Item(price: 10, count: 4),

            "Pretzels": Item(price: 7, count: 11)

        ]

        var coinsDeposited = 0

        func dispenseSnack(snack: String) {

            print("Dispensing (snack)")

        }

        

        func vend(itemNamed name: String) throws {

    //throws关键字,定义了该函数可抛出throw错误,在调用此方法的地方,必须要么直接处理这些错误,使用do-catch语句,try?或try!;要么继续将这些错误传递下去

    //guard ... else{ ... } ,表达式为false时执行else,为true时跳过else的代码,执行后面的代码

            guard var item = inventory[name] else {

                throw VendingMachineError.InvalidSelection  //这里的throw 抛出指定错误类型到外部,通过其它方式处理该错误

            }

            

            guard item.count > 0 else {

                throw VendingMachineError.OutOfStock

            }

            

            guard item.price <= coinsDeposited else {

                throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)

            }

            

            coinsDeposited -= item.price

            --item.count

            inventory[name] = item

            dispenseSnack(name)

        }

    }

    let favoriteSnacks = [

        "Alice": "Chips",

        "Bob": "Licorice",

        "Eve": "Pretzels",

    ]

    func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

        let snackName = favoriteSnacks[person] ?? "Candy Bar"

    //空合运算符"a ?? b",a必须为可选类型,若a有值则取值,无值则取b的值,类型必须一样

        try vendingMachine.vend(itemNamed: snackName)

    }

    //=======do-catch=========

    var vendingMachine = VendingMachine()

    vendingMachine.coinsDeposited = 8

    do {

        try buyFavoriteSnack("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.”

  • 相关阅读:
    1001 字符串“水”题(二进制,map,哈希)
    hzau 1210 Happiness
    hzau 1209 Deadline(贪心)
    hzau 1208 Color Circle(dfs)
    hzau 1207 Candies
    hzau 1206 MathematicalGame
    hzau 1205 Sequence Number(二分)
    hzau 1204 Escape from the Darkness
    Calculator 2
    Calculator
  • 原文地址:https://www.cnblogs.com/susufufu/p/5705616.html
Copyright © 2020-2023  润新知