iOS Swift - Error Handling

longlivedrgn·2022년 9월 10일
0

swift문법

목록 보기
20/36
post-thumbnail

Error Handling

  • 오류 정의 정의/ throw / try do - catch까지 사용한 예

    ‼️⁉️ throws를 하는 함수를 사용하려면 무조건 앞에 try를 붙혀주어야된다.

// enum형으로 error타입명 정의
enum DataError : Error { // Error 프로토콜을 구현한 것은 오류 타입으로 사용하라는 일종의 가독성 표시
    case overSizeYear
    case incorrectData(part: Int)
}

// 오류가 나는 조건을 throws와 함께 배치 -> throw 문 추가
func getNextYearAndThrows(paramYear: Int) throws -> Int {
    guard paramYear <= 2020 else {
        throw DataError.overSizeYear
    }
    
    guard paramYear >= 0 else {
        throw DataError.incorrectData(part: paramYear)
    }
    
    return paramYear+1
}

// 실제로 응용프로그램에서 불러올 함수 -> try do catch 문 사용
func getNextYear(paramYear: Int) -> Int {
    var year: Int = 0
    do {
        year = try getNextYearAndThrows(paramYear: paramYear)
    } catch DataError.overSizeYear {
        print("년도 초과해서 입력하였습니다")
    } catch DataError.incorrectData(let part){
        print("입력한 값이 \(part)이므로 오류입니다.")
    } catch {
        print("default error catch")
    }
    
    return year
}

let a = getNextYear(paramYear: -999) // 입력한 값이 -999이므로 오류입니다.

Localized error와 errordescription 사용하기

import Foundation

enum StockError: LocalizedError {
    case noCorrespondingFruit
    case notEnoughToMakeJuice
    case notEnoughToChange
    
    var errorDescription: String? {
        switch self {
        case .noCorrespondingFruit:
            return "일치하는 과일이 없습니다."
        case .notEnoughToMakeJuice:
            return "재료가 모자라요."
        case .notEnoughToChange:
            return "더 이상 변경할 수 없어요."
        }
    }
}

func tryError(if x: Int) throws {
    if x == 0 {
        throw StockError.noCorrespondingFruit
    } else if x == 1 {
        throw StockError.notEnoughToMakeJuice
    } else {
        throw StockError.notEnoughToChange
    }
}

func catchError(if x: Int) {
    do {
        try tryError(if: x)
    } catch  {
        print(error.localizedDescription)
    }
}

catchError(if: 0) // 일치하는 과일이 없습니다.
catchError(if: 1) // 재료가 모자라요.
catchError(if: 2) // 더 이상 변경할 수 없어요.

오류의 종류를 정의하기

  • enum 형식으로 오류의 종류를 정의할 수 있다.
enum DataParsingError: Error {
    case invalidType
    case invalidField
    case missingRequiredField(String)
}

오류를 던지기(throw)

  • 만약 아래와 같은 코드를 작성했다고 하자
func parsing(data: [String: Any]) {
    guard let _ = data["name"] else {
        return
    }
    guard let _ = data["age"] as? Int else {
        return
    }
}
  • 위의 코드는 else일 경우 에러가 나와 return을 하면서 끝내게 되는데 만약 else일 경우 미리 정의해 놓은 오류를 던지고 싶다면? 아래와 같이 throw와 throws를 코드에 넣어주면 된다.
func parsing(data: [String: Any]) throws {
    guard let _ = data["name"] else {
        throw DataParsingError.missingRequiredField("name")
    }
    guard let _ = data["age"] as? Int else {
        throw DataParsingError.invalidType
    }
}

try?

  • 에러가 발생할 수 있는데 한번 실행해보는 것이다. ?의 경우 에러가 발생할 경우 nil을 리턴한다.
try? parsing(data: [:]) //nil

tyr!

  • 에러가 발생하지 않을거라고 확신할 때만 사용을 한다.

Do- Catch

  • 기본 꼴은 아래와 같다.
do {
    try expression
    statements
} catch pattern {
    statements
} catch pattern where condition {
    statements
}
  • do 블록을 실행해서 만약 error가 나오게 되면 그 에러가 무엇이냐에 따라서 위에서 부터 아래로 확인해가며 catch 블록이 선택되어 실행이 된다.
do {
    try parsing(data: [:])
} catch DataParsingError.invalidType {
    print("invalid type error")
} catch {
    print("handle error")
}
  • 만약 pattern이 없을 경우, 아래와 같은 방식으로 error handling을 자주 해준다.
// 만약 pattern이 없을 경우 아래와 같은 방식으로 error handling을 자주한다.
func handleError() throws {
    do {
        try parsing(data: ["name":""])
    } catch {
        if let error = error as? DataParsingError {
            switch error {
            case .invalidType:
                print("invalid type")
            default:
                print("handle error")
            }
        }
    }
}

Defer

  • 말그대로 해당 코드를 맨 마지막에 실행히시키는 것이다
  • 함수를 종료하기 직전에 정리해야 하는 변수나 상수를 처리하는 용도

출처/참고 - https://babbab2.tistory.com/80

0개의 댓글