LoginSignup
11
8

More than 3 years have passed since last update.

Swift エラーハンドリングの基本

Posted at

この記事は何?

Swiftプログラミングでのエラー処理について、調べました。
忘備録を兼ねて投稿します。
参考記事: Swift Language Guide

実行環境

Swift5.x
Xcode11 beta2
macOS 10.14 Mojave

ハンズオン

エラーを定義して、スローするプログラムを記述します。

こんなクラスがあったとして

自動販売機をコードで表現しています。

自動販売機のクラス
// 商品の金額と残り個数
struct ItemInfo {
    var price: Int
    var count: Int
}

// 自動販売機
class VendingMachine {
    var inventories = [String: ItemInfo]()  // 在庫の商品
    var coinsDeposited = 0  // 預かり金

    // 商品を販売
    func vend(itemNamed name: String) {
        let selectedItem = inventories[name]
        coinsDeposited -= selectedItem.price

        var newItem = selectedItem
        newItem.count -= 1
        inventories[name] = newItem   // updating a value

        print("Dispensing \(name)")
    }
}

自販機のインスタンス

自動販売機のインスタンス drinkStand を生成して、"Coke" を買います。

自販機インスタンスを生成する
let drinkStand = VendingMachine()

// ドリンクを補填
drinkStand.inventories = [
    "Coke" : ItemInfo(price: 120, count: 7),
    "Soda" : ItemInfo(price: 80, count: 3),
    "Milk" : ItemInfo(price: 100, count: 10)]

// コーラを買う
drinkStand.vend(itemNamed: "Coke")

起こりうるエラー

この自販機プログラムでは、以下のようなエラーが発生するかもしれません。

  • 無効な商品を選択
  • 支払額が不足
  • 在庫なし

自販機で起こりうるエラー を列挙型を使って、コードで定義します。
このとき、Error プロトコルに準拠させておくと、Swiftが自動的にエラーハンドリングの対象にしてくれます。

エラーの定義
enum VendingMachineError: Error {
    case invalidSelection   // 無効な選択
    case insufficientFunds(coinsNeeded: Int)    // 支払額が不足
    case outOfStock // 在庫なし
}

Error プロトコル

具体的な実装はなく、カラのプロトコルです。
準拠に適合するために、何か特別なことをする必要はありません。

エラーをthrow(スロー)する

自販機クラス内のエラーが発生しそうな行で、エラーをスロー します。
throw キーワードを使います。
どんなエラーが発生したかは、VendingMachineError 型を使って指定できます。
この時点で、vend(itemNamed:) メソッドはエラーを throw するかもしれないメソッドになりました。
メソッド宣言のパラメータ直後に throws キーワードを記述します。

エラーをスローする
class VendingMachine {
    var inventories = [String: ItemInfo]()
    var coinsDeposited = 0

    func vend(itemNamed name: String) throws {
        // 無効な商品を選択したら、エラーをスローする
        guard let selectedItem = inventories[name] else {
            throw VendingMachineError.invalidSelection
        }
        coinsDeposited -= selectedItem.price

        var newItem = selectedItem
        newItem.count -= 1
        inventories[name] = newItem

        print("Dispensing \(name)")
    }
}

エラーをスローする関数の定義

throw キーワードと throws キーワードは間違いやすいので、気をつける必要があります。

スロー関数の宣言(例)
// エラーをスローできる関数の宣言 
func canThrowErrorsMethod() throws -> <ReturnType>

// エラーをスローしない関数の宣言
func cannotThrowErrorsMethod() -> <ReturnType>
11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8