切り替え構文きりかえこうぶん:エラー処理えらーしょり


  • Error Handling→プログラムにエラーが発生したときにエラーを検出して復元する一連のプロセス
  • エラーの表示
  • swiftのエラーは、Errorプロトコルに適合するタイプ値によって
  • を表す.
  • エラータイプ(主に列挙型)このプロトコル
  • を採用
    ex.自動販売機エラーのタイプを列挙する
    enum VendingMachineError: Error {
        case invalidSelection
        case insufficientFunds(coinsNeeded: Int)
        case outOfStock
    }
    →以上のプロトコルはErrorプロトコルを採用
    最も一般的で便利な
  • 列挙エラータイプ
    **前述したように、予め予測されているエラーのタイプは、エラーにより次のステップで実行される動作が正常に行われない場合は、エラー(Throw error)を投げ出せばよい.
    →throw文でエラーを投げ出す.
    ex. throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
    エラーのキャプチャと処理
    エラーを投げ出すこともできますが、投げ出されたエラーを処理するためにコードを別途作成する必要があります.
    ex.投げ出した誤りを探し出して解決する
    ex.エラーを通知し、選択権限をユーザーに渡し、次に何をするかを決定するコードをユーザーに導く
  • エラーを処理する4つの方法:
  • 関数のエラー通知を関数のコードを呼び出すには、
  • を実行します.
  • do-catch構文を使用してエラー
  • を処理する方法
  • 参照値を使用してエラーを処理する方法(?)
  • エラーが発生しないようにする方法(!)
  • 通知関数エラー
  • tryキーワードから投げ出されたエラー
  • try, try?, try!
  • 関数、メソッド、および頭文字のパラメータの後にthrowsキーワードを使用して、エラー
  • を投げ出すことができます.
    典型的な関数:func cannotThrowErrors()→String
    エラー放出関数:func canThrowErrors()throws→String
    注:関数、メソッド、およびthrowsを含むアルファベット記号は、通常の関数、メソッド、およびアルファベット記号として再定義できません.厳格なタイプ区分
    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),
            "Biscuit": Item(price: 7, count: 11)
        ]
        
        var coinsDeposited = 0
        
        func dispense(snack: String) {
            print("\(snack) 제공")
        }
        
        func vend(itemNamed name: String) throws {
            guard let item = self.inventory[name] else {
                throw VendingMachineError.invalidSelection
            }
            
            guard item.count > 0 else {
                throw VendingMachineError.outOfStock
            }
            
            guard item.price <= self.coinsDeposited else {
                throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - self.coinsDeposited)
            }
            
            self.coinsDeposited -= item.price
            
            var newItem = item
            newItem.count -= 1
            self.inventory[name] = newItem
            
            self.dispense(snack:name)
        }
    }
    
    let favoriteSnacks = [
        "yagom": "Chips",
        "jinsung": "Biscuit",
        "heejin": "Chocolate"
    ]
    
    func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
        let snackName = favoriteSnacks[person] ?? "Candy Bar"
        try vendingMachine.vend(itemNamed: snackName)
    }
    
    struct PurchasedSnack {
        let name: String
        init(name: String, vendingMachine: VendingMachine) throws {
            try vendingMachine.vend(itemNamed: name)
            self.name = name
        }
    }
    
    let machine: VendingMachine = VendingMachine()
    machine.coinsDeposited = 30
    
    var purchase: PurchasedSnack = try PurchasedSnack(name: "Biscuit", vendingMachine: machine)
    // Biscuit 제공
    
    print(purchase.name)    // Biscuit
    
    for (person, favoriteSnack) in favoriteSnacks {
        print(person, favoriteSnack)
        try buyFavoriteSnack(person: person, vendingMachine: machine)
    }
    // yagom Chips
    // Chips 제공
    // jinsung Biscuit
    // heejin Chocolate
    
    // 오류 발생!!
    do-catch構文を使用してエラーを処理する
  • 関数、メソッド、頭文字Riserにエラーが投げ出された場合、エラーを渡すコードブロックはdo-catch構文を使用してエラーを処理する必要があります.
  • doセクションのコードにエラーが投げ出された場合、catchセクションは対応する処理
  • にエラーを送信します.
    do {
    	try 오류 발생 가능코드
    	오류가 발생하지 않으면 실행할 코드
    } catch 오류 패턴1{
    	처리코드
    } catch 오류 패턴2 where 추가조건{
    	처리코드
    }
    func tryingVend(itemNamed: String, vendingMachine: VendingMachine) {
        do {
            try vendingMachine.vend(itemNamed: itemNamed)
        } catch VendingMachineError.invalidSelection {
            print("유효하지 않은 선택")
        } catch VendingMachineError.outOfStock {
            print("품절")
        } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
            print("자금부족 - 동전 \(coinsNeeded)개를 추가로 지급해주세요.")
        } catch {
            print("그 외 오류 발생 : ", error)
        }
    }
    傍観者値でエラーを処理
  • try? エラー
  • を処理するには、傍観者値に変換することもできる.
  • try?エラーが実行され、投げ出された場合、コードの戻り値はnil(
  • )です.
    func someThrowingFunction(shouldThrowError: Bool) throws -> Int {
        
        if shouldThrowError {
            
            enum SomeError: Error {
                case justSomeError
            }
            
            throw SomeError.justSomeError
        }
        
        return 100
    }
    
    let x: Optional = try? someThrowingFunction(shouldThrowError: true)
    print(x)    // nil
    
    let y: Optional = try? someThrowingFunction(shouldThrowError: false)
    print(y)    // Optional(100)
    →x,yも、戻りタイプがnilの場合に取得するには、すべてオープンとして宣言する必要があります.
    エラーが発生しないようにする方法
  • try!
  • 置換
  • が失敗すると、ランタイムエラーが発生し、アプリケーション
  • を強制的に閉じる.
    func someThrowingFunction(shouldThrowError: Bool) throws -> Int {
        
        if shouldThrowError {
            
            enum SomeError: Error {
                case justSomeError
            }
            
            throw SomeError.justSomeError
        }
        
        return 100
    }
    
    let y: Int = try! someThrowingFunction(shouldThrowError: false)
    print(y)    // 100
    
    let x: Int = try! someThrowingFunction(shouldThrowError: true)	// 런타임 오류!!
    投げ直す
  • rethrowsキーワード→自己パラメータとして渡す関数を表すエラー
  • の戻りを可能にするには、エラーが発生する可能性のある少なくとも1つの関数をパラメータとして渡す必要があります.
  • func someThrowingFunction() throws {
        
        enum SomeError: Error {
            case justSomeError
        }
        
        throw SomeError.justSomeError
    }
    
    // 다시던지기 함수
    func someFunction(callback: () throws -> Void) rethrows {
        try callback()   // 다시던지기 함수는 오류를 다시 던질 뿐 따로 처리하지는 않습니다.
    }
    
    do {
        try someFunction(callback: someThrowingFunction)
    } catch {
        print(error)
    }
    // justSomeError
    後処理遅延
  • は、コードブロックを終了する前に実行する必要があるコード
  • を記述することができるようになった.
  • コードがどのようにブロックから離れるかにかかわらず、実行すべき最終タスク
  • を実行することができる.
    ex.ファイルを開くときにエラーが発生しました.コードがブロックから離れても、正常にファイルを閉じてメモリから解放する必要があります.そのため、defer構文内でファイルを閉じるコードを追加できます.
    func someThrowingFunction(shouldThrowError: Bool) throws -> Int {
        
        defer {
            print("First")
        }
        
        if shouldThrowError {
            
            enum SomeError: Error {
                case justSomeError
            }
            
            throw SomeError.justSomeError
        }
        
        defer {
            print("Second")
        }
        
        defer {
            print("Third")
        }
        
        return 100
    }
    
    try? someThrowingFunction(shouldThrowError: true)
    // First
    // 오류를 던지기 직전까지 작성된 defer 구문까지만 실행됩니다.
    
    try? someThrowingFunction(shouldThrowError: false)
    // Third
    // Second
    // First
    
    // 코드 28-13 복합적인 defer 구문의 실행 순서
    func someFunction() {
        print("1")
        
        defer {
            print("2")
        }
        
        do {
            defer {
                print("3")
            }
            print("4")
        }
        
        defer {
            print("5")
        }
        
        print("6")
    }
    
    someFunction()
    
    // 1
    // 4
    // 3
    // 6
    // 5
    // 2