[Swift] Error Handling

Swiftでのエラーハンドリングはdo-catchの中で行います。
Objective-C以上にエラーハンドリングが必要になってくるので、Objective-CからSwiftに来た場合は注意が必要です。
(実際にコードを書いてみると結構使う事になる)

  • Errorプロトコルを継承することでエラーを定義できる
  • Errorはdo - catchの中でtryキーワードと使う
  • deferキーワードを使って関数の最後に必ず実行される処理を記述できる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Errorプロトコルを継承してエラーを作成できる
enum PrinterError: Error {
    case outOfPaper
    case noToner
    case onFire
}
 
// エラーをthrowする関数はthrowsキーワードで定義する
func send(job: Int, toPrinter printerName:String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    if printerName == "On Fire" {
        throw PrinterError.onFire
    }
 
    return "Job sent"
}
 
do {
    // let printerResponse = try send(job: 400, toPrinter: "Bi Sheng")
    let printerResponse = try send(job: 400, toPrinter: "Never Has Toner")
    print(printerResponse)
} catch {
    print(error)
}
 
// エラー毎に処理を分けることも可能
do {
    // let printerResponse = try send(job: 1440, toPrinter: "Musashi")
    // let printerResponse = try send(job: 1440, toPrinter: "Never Has Toner")
    let printerResponse = try send(job: 1440, toPrinter: "On Fire")
    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)
}

try?キーワードでもハンドリングできます。
エラーの場合にnilになるので、詳細が不要な場合はこちらでOK

1
2
3
4
5
6
7
8
9
10
// try?でもエラーハンドリング可能
// この場合、Errorがthrowされるとnilになる
if let printerSuccess = try? send(job: 1884, toPrinter: "Fuji") {
    print(printerSuccess)
}
 
if let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner") {
    // ここは呼ばれない (printerfailureがnilになるので)
    print(printerFailure)
}

finaly的な処理(defer)

関数の最後に必ず処理を行いたい場合はdeferキーワードを使います。
これを使うと、関数の最後に処理が実行されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]
 
func fridgeContains(_ food: String) -> Bool {
    // deferキーワードを書くと必ず関数の最後に実行される
    // 最後のクリーンアップ処理を記述するのに使える
    defer {
        fridgeIsOpen = false
    }
 
    fridgeIsOpen = true
    let result = fridgeContent.contains(food)
    return result
}
 
let retVal = fridgeContains("banana")
print("retVal = \(retVal)")
print(fridgeIsOpen)  // falseになる

参考URL

0 件のコメント :

コメントを投稿