見出し画像

Swiftを始めよう! - Error Handling

何かエラーが出る可能性がある場合にその処理を定義しておくことができます。

エラーの型をenumでプロトコルErrorとして定義します。

    enum PrinterError: Error {
        case outOfPaper
        case noToner
        case onFire
    }


エラーの可能性がある関数は" throws"をつけておきます。

func send(job: Int, toPrinter printerName: String) throws -> String {}

エラーの場合の条件とエラーの場合の処理を書きます。エラーの場合の処理はthrowを書いてその後に内容を書きます。以下の場合はenumで定義したエラーで処理するようにしています。

if printerName == "Never Has Toner" {
    throw PrinterError.noToner
}

関数全体としては以下として、エラーがなければ"Job sent"を返します。

  func send(job: Int, toPrinter printerName: String) throws -> String {
        if printerName == "Never Has Toner" {
            throw PrinterError.noToner
        }
        return "Job sent"
    }

これでエラーの可能性のある関数定義ができました。

エラーのある関数ができただけではエラー処理はできません。エラーを処理するには、いくつかの方法があり、その1 つの方法は、do-catch を使用することです。

do ブロック内で、"try"をまず書きます。 、その後にエラーのある可能性がある関数を書きます。

catch ブロック内にエラーの場合の処理を書きます。

    do {
        let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
        print(printerResponse)
    } catch {
        print(error)
    }

この場合エラーなく正常に処理されるので"Job sent"と出力されます。

enumで定義したのエラーを使うことで複数の catch ブロックを作って特定のエラーの処理をすることができます、

    do {
        let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
        print(printerResponse)
    } catch PrinterError.onFire {
        print("I'll just put this over here, with the rest of the fire.")
    } catch let printerError as PrinterError {
        print("Printer error: \(printerError).")
    } catch {
        print(error)
    }

"Job sent"と出力されます。

try?

エラーを処理する別の方法は、try? を使用することです。 結果をoptionaに変換します。
関数がエラーをスローした場合、特定のエラーは破棄され、結果は nil になります。 それ以外の場合、結果は、関数が返した値を含むオプションです。

エラーが発生しても無視でき、コンパイルエラーが発生することはありません。

    let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")

こちらは"Job sent"となりますが

    let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")

こちらはエラー発生("Never Has Toner"でエラーとなる)なので"nil"となります。

defer

defer を使用して、関数内の他のすべてのコードの後、関数が戻る直前に実行されるコード ブロックを記述します。 関数がエラーをスローするかどうかに関係なく、コードが実行されます。 セットアップ コードとクリーンアップ コードは別々のタイミングで実行する必要がありますが、defer を使用して並べて記述することができます。

    var fridgeIsOpen = false
    let fridgeContent = ["milk", "eggs", "leftovers"]

    func fridgeContains(_ food: String) -> Bool {
        fridgeIsOpen = true
        defer {
            fridgeIsOpen = false
        }

        let result = fridgeContent.contains(food)
        return result
    }

    fridgeContains("banana")
    
    print(fridgeIsOpen)

"false"と出力されます。


参考になるサイトです


この記事が気に入ったらサポートをしてみませんか?