エラー処理


エラー処理構文


エラーの理解

  • エラーのタイプは次のとおりです.
    1)コンパイル時のエラー=>>sweet構文に関連するエラー(コンパイラから事前に知っておく必要があるというメッセージが表示されます)
    2)運転中にエラーが発生しました=>
  • ランタイムエラー=>>crash(アプリケーション強制クローズ)
    ==>>発生する可能性のあるエラーを事前に処理すると、強制終了(開発者が処理しなければならないエラー)
  • はしません.

    (実行時)エラー処理が必要なのはなぜですか?

     - 앱이 실행하는 중간에 왜 꺼질까?
     
     - 어떤 얘기치 못한 상황이 발생할 수 있음
     - (네트워크 통신을 하는 등의 경우에서) 서버에서 데이터를 못 받아와서 ==> 꺼짐
    
     - 앱이 그냥 꺼지는 게 좋은가? 아니면 예를들어 "서버에서 문제가 발생했습니다. 
     잠시뒤에 다시 접속해 주세요"라고 알려주는 것이 좋은 가?
     
     - 프로세스 중에서, 예외적인 상황(에러)이 발생하는 것이 미리 가능성 등을 처리해 놓으면
       앱이 무작정 꺼지는 것을 예방할 수 있음 ⭐️
    
    
     - 에러는 일반적으로 동작. 즉, 함수의 처리과정에서 일어남
     - 함수를 정의할때
     예외적인 일이 발생하는 경우가 발생할 수 있는 함수라고 정의하고 처리하는 과정을 배울 것임
    
    
     - (에러 발생 가능)함수 ====>  함수 실행시에 조금 다르게 처리해야함(에러 처리) ⭐️

    エラー処理手順(手順3)


    1)定義エラー(事前定義で発生するエラー)

    enum HeightError: Error {    //에러 프로토콜 채택 (약속)
        case maxHeight
        case minHeight
    }

    2)エラーが発生する可能性のある関数の定義

    func checkingHeight(height: Int) throws -> Bool {    
    // (에러를 던잘수 있는 함수 타입이다)
        
        if height > 190 {
            throw HeightError.maxHeight
        } else if height < 130 {
            throw HeightError.minHeight
        } else {
            if height >= 160 {
                return true
            } else {
                return false
            }
        }
    }

    3)エラーが発生する可能性のある関数の処理(関数の実行)


    ===>既存とは少し異なります(try文とdo-catch文で処理)
    do {
        
        let isChecked = try checkingHeight(height: 200)
        print("놀이기구 타는 것 가능: \(isChecked)")
        
    } catch {
        
        print("놀이기구 타는 것 불가능")
        
    }
  • do block-関数によって正常に処理するblock
  • catch block-処理を実行するblock
  • (関数がエラーを投げた場合)

    エラーの処理方法-try/try?/try!


    1)エラー式の処理方法
     do {
        let isChecked = try checkingHeight(height: 200)
        
        if isChecked {
            print("청룡열차 가능")
        } else {
            print("후룸라이드 가능")
        }
    } catch {
        print("놀이기구 타는 것 불가능")
    }
    2) try? (オフセット量)===>オフセットタイプに復元
    (1)通常は=>(通常)戻りタイプで返す
    (2)エラーが発生した場合=>nilが返す
    let isChecked = try? checkingHeight(height: 200) 
    3) try! (Forced trie)==>>エラーが発生しない場合にのみ使用可能
    (1)通常は=>(通常)戻りタイプで返す
    (2)エラー発生時==>ランタイムエラー
    let isChecked2: Bool = try! checkingHeight(height: 150)  // Bool

    Catch Block処理方法


    catch blockはdo blockで発生したエラーを処理するblockです
    すべてのエラーを処理する必要があります(グローバルスキャンですべてのエラーを処理しない場合、コンパイルエラーは発生しません).
    パターンが存在する場合(すべてのエラーを別々に処理する必要があります)
    do {
        
        let isChecked = try checkingHeight(height: 100)
        print("놀이기구 타는 것 가능: \(isChecked)")
        
    } catch HeightError.maxHeight  {    
    // where절을 추가해서, 매칭시킬 에러패턴에 조건을 추가할 수 있음
        
        print("키가 커서 놀이기구 타는 것 불가능")
        
    } catch HeightError.minHeight {      // 생략가능
        
        print("키가 작아서 놀이기구 타는 것 불가능")
        
    }
    catchモードなしで処理可能
    do {
        
        let isChecked = try checkingHeight(height: 100)
        print("놀이기구 타는 것 가능: \(isChecked)")
        
    } catch {    // error 상수를 제공 (모든 에러가 넘어옴)
        print(error.localizedDescription)
        
        if let error = error as? HeightError {    
        // 실제 우리가 정의한 구체적인 에러 타입이 아니고, 에러 타입(프로토콜)이 넘어올 뿐
            switch error {
            case .maxHeight:
                print("키가 커서 놀이기구 타는 것 불가능")
            case .minHeight:
                print("키가 작아서 놀이기구 타는 것 불가능")
            }
        }
    }
    

    放出エラーの関数の処理

    // 에러정의
    enum SomeError: Error {
        case aError
    }
    
    
    // 에러를 던지는 함수 정의 (무조건 에러를 던진다고 가정)
    func throwingFunc() throws {
        throw SomeError.aError
    }
    
    
    // 에러의 처리
    do {
        try throwingFunc()
    } catch {
        print(error)
    }
    
    通常の関数として処理
    // 함수 내부에서 do-catch문으로 에러를 처리
    // 즉, 발생한 에러를 catch블럭에서 받아서 알맞은 처리
    
    func handleError() {
        do {
            try throwingFunc()
        } catch {
            print(error)
        }
    }
    
    
    handleError()

    1-投げ関数で再度投げ間違い

    /**====================================================
     - 함수 내에서 에러를 직접처리하지 못하는 경우, 에러를 다시 던질 수 있음
     ====================================================**/
    
    func handleError1() throws {
        //do {
        try throwingFunc()
        //}                     // catch블럭이 없어도 에러를 밖으로 던질 수 있음 ⭐️
    }
    
    
    
    do {
        try handleError1()   // 에러를 받아서 처리 가능
    } catch {
        print(error)
    }
    

    2-ロールバック関数を使用したロールバックエラー(ロールバックキー)

    /**================================================================
     - 에러를 던지는 throwing함수를 파라미터로 받는 경우, 내부에서 다시 에러를 던지기 가능
     - rethrows키워드 필요 (Rethrowing메서드)
     ==================================================================**/
    
    
    // 다시 에러를 던지는 함수(방법1)
    func someFunction1(callback: () throws -> Void) rethrows {
        try callback()             // 에러를 다시 던짐(직접 던지지 못함)
        // throw (X)
    }
    
    
    // 다시 에러를 던지는 함수(방법2) - 에러변환
    func someFunction2(callback: () throws -> Void) rethrows {
        enum ChangedError: Error {
            case cError
        }
        
        do {
            try callback()
        } catch {   // catch구문에서는 throw (O)
            throw ChangedError.cError    // 에러를 변환해서 다시 던짐
        }
    }
    
    
    
    
    // 실제 에러를 다시던지는(rethrowing)함수를 처리하는 부분
    
    do {
        try someFunction1(callback: throwingFunc)
    } catch {
        print(error)
    }
    
    
    
    do {
        try someFunction2(callback: throwingFunc)
    } catch {
        print(error)
    }

    メソッド/作成者

    /**=======================================================================
     - 에러는 1)Throwing함수 뿐만아니라, 2) 메서드와 3)생성자에도 적용 가능
     - 에러는 던질 수 있는 메서드는 Throwing메서드, 에러는 던질 수 있는 생성자는 Throwing생성자
     =========================================================================**/
    
    // 에러 정의
    
    enum NameError: Error {
        case noName
    }
    
    
    
    // 생성자와 메서드에도 적용 가능
    class Course {
        var name: String
        
        init(name: String) throws {
            if name == "" {
                throw NameError.noName
            } else {
                self.name = name
                print("수업을 올바르게 생성")
            }
        }
        
    }
    
    
    
    // 에러 처리 (생성자에 대한)
    
    do {
        let _ = try Course(name: "스위프트5")
    } catch NameError.noName {
        print("이름이 없어 수업이 생성 실패하였습니다.")
    }

    作成者とメソッドの再定義

    class NewCourse: Course {
        
        override init(name: String) throws {
            try super.init(name: name)
            
        }
    }
    
    
    /**=================================================================
     - Throwing 메서드/생성자는 재정의할 때, 반드시 Throwing메서드/생성자로 재정의해야함
       (Throwing 메서드/생성자를 일반 메서드/생성자로 재정의 불가)
    
     - 일반 메서드/생성자를 Throwing 메서드/생성자로 재정의 하는 것은 가능
       (일반 메서드/생성자의 범위가 더 큼)
     
     [상속관계에서]
     - (상위) throws    (하위) throws재정의    (O 가능)
     
     - (상위) 일반       (하위) throws재정의    (O 가능)
       (상위) throws    (하위) 일반재정의       (X 불가능)
     
     - (상위) throws    (하위) rethrows재정의  (O 가능)
       (상위) rethrows  (하위) throws재정의    (X 불가능)
    
     - Throwing메서드와 Rethrowing메서드를 비교하면 Rethrowing메서드의 범위가 더 작음
     ===================================================================**/