Swift -エラー処理、アサーションと前提条件

5993 ワード

エラー処理は、実行中にプログラムが発生する可能性があるエラー条件に対応するために使用できます.
  • 関数は、その宣言にthrowsキーワードを含めることでエラーをスローできることを示します.エラーをスローできる関数を呼び出すと、tryキーワードを式に追加します.Swiftはcatch句で処理されるまで自動的に現在のスコープからエラーを伝播します.
  • A DOステートメントは、1つ以上のキャッチ節にエラーを伝播させることができる新しい包含範囲を作成します.
  • 文法do {
    try canThrowAnError()
    // no error was thrown
    } catch {
    // an error was thrown
    }
    エラーは、エラープロトコルに従うタイプの値によって表されます.この空のプロトコルは、型がエラー処理に使用できることを示します.
  • 列挙体は、関連するエラー条件のグループをモデル化するのに適しています.そして、関連する値が通信されるエラーの性質に関する追加情報を考慮に入れます.throwステートメントを使用してエラーをスローできます.
  • 例:
    enum VendingMachineError: Error {
        case invalidSelection
        case insufficientFunds(coinsNeeded: Int)
        case outOfStock
    }
    
    throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
    

    取り扱いエラー


    Swiftでエラーを処理する4つの方法があります.
  • 関数から関数を呼び出すコードにエラーを伝播します.
  • Do catchステートメントを使用してエラーを処理します.
  • オプションの値としてエラーを処理します.
  • は、エラーが発生しないことを主張する.
  • 投げる関数を用いた伝搬誤差

  • スロー関数、メソッド、初期化子はスローされてマークされます.
  • 関数をスローするだけでエラーが伝播する.ノンスロー関数内でスローされたエラーは、関数内で処理する必要があります.
  • 例:
    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 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)")
        }
    }
    
    VenD ( ItemName :)メソッドはスローされたエラーを伝播します.このメソッドを呼び出すコードは、do catch文を使用してエラーを処理する必要があります.または試みる!またはそれらを伝播し続ける.

    do catchを使用したエラー処理


    catchステートメントを使用して、コードのブロックを実行してエラーを処理できます.DO句内のコードによってエラーがスローされた場合、catch句に対してどちらがエラーを処理できるかを判断します.
    例:
    var vendingMachine = VendingMachine()
    vendingMachine.coinsDeposited = 8
    do {
        try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
        print("Success! Yum.")
    } 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.")
    } catch {
        print("Unexpected error: \(error).")
    }
    
  • キャッチ節がエラーを処理しない場合、エラーは周囲のスコープに伝播します.しかしながら、伝播されたエラーは若干の周囲の範囲によって扱われなければなりません.
  • ノンスロー関数では、囲んだdo catch文はエラーを処理しなければなりません.
  • 投機機能の中で、
  • は、囲んでいるDocatchステートメントか呼び出し元がエラーを処理しなければなりません.
  • エラーがトップレベルスコープに処理されない場合は、ランタイムエラーが発生します.
  • 例:
    func nourish(with item: String) throws {
        do {
            try vendingMachine.vend(itemNamed: item)
        } catch is VendingMachineError {
            print("Couldn't buy that from the vending machine.")
        }
    }
    
    do {
        try nourish(with: "Beet-Flavored Chips")
    } catch {
        print("Unexpected non-vending-machine-related error: \(error)")
    }
    

    エラーを任意の値に変換


    試して?オプションの値に変換することでエラーを処理するために使用できます.試行を評価している間、エラーが投げられるならば?式の式の値はNILです.
    例:
    func someThrowingFunction() throws -> Int {
        // ...
    }
    
    let x = try? someThrowingFunction()
    

    エラー伝播を無効にする


    スロー機能またはメソッドがランタイムでエラーをスローしないことを確認した場合は、tryを試してください!式の前にエラー伝播を無効にします.エラーが実際にスローされると、ランタイムエラーが発生します.
    例:
    let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
    

    クリーンアップアクションの指定


    コード実行がコードの現在のブロックを離れる直前に、一連のステートメントを実行するためにdeferステートメントを使用します.このステートメントでは、エラーがスローされたかどうか、またはreturnまたはbreakのようなステートメントのために実行が現在のブロックのブロックをどのように残しているかに関係なく、実行する必要があります必要なクリーンアップを行うことができます.
  • 延期された文には、breakまたはreturn文のような転送制御文、またはエラーをスローします.
  • - deferredアクションは、ソースコードに書かれている順序の逆で実行されます.つまり、最初のdeferステートメントのコードが最後に実行され、2番目のdeferステートメントのコードが2番目から最後まで実行されます.
    例:
    func processFile(filename: String) throws {
        if exists(filename) {
            let file = open(filename)
            defer {
                close(file)
            }
            while let line = try file.readline() {
                // Work with the file.
            }
        }
    }
    

    アサーションと前提条件


    アサーションと前提条件は実行時に起こるチェックです.任意の更なるコードを実行する前に必須条件が満たされることを確認するためにそれらを使用します.assertionまたは前提条件の論理条件がtrueに評価されるならば、コード実行は通常通り続きます.条件がfalseに評価されるならば、プログラムの現在の状態は無効です;コードの実行が終了し、アプリケーションが終了します.
  • 主張と前提条件は、回復可能であるか予想されたエラーに使用されません.失敗したアサーションや前提条件が無効なプログラム状態を示すため、失敗したアサーションをキャッチする方法はありません.
  • は、無効な状態が検出されるとすぐに実行を停止するために使用されますまた、その無効な状態に起因する損害を制限するのに役立ちます.
  • アサーションはデバッグビルドだけでチェックされます、しかし、前提条件はデバッグと生産ビルディングの両方でチェックされます.
  • アサーションは、開発中にミスや不適切な仮定を見つけるのに役立ちます.前提条件は、生産の問題を検出するのに役立ちます.
  • 例:
    let age = -3
    assert(age >= 0, "A person's age can't be less than zero.")
    
    or
    if age > 10 {
        print("You can ride the roller-coaster or the ferris wheel.")
    } else if age >= 0 {
        print("You can ride the ferris wheel.")
    } else {
        assertionFailure("A person's age can't be less than zero.")
    }
    
    precondition(index > 0, "Index must be greater than zero.")