iOS 개발 기록

에러 처리 본문

Swift

에러 처리

택꽁이 2022. 10. 24. 22:41
728x90

에러 처리

Tags: Swift

에러의 표시와 발생

Swift에서 에러는 Error 프로토콜을 준수하는 타입의 값으로 표현된다. 에러는 주로 열거형(enum)을 통해 그룹화 되어 관리된다.

enum LogViewError: Error {
  case documentDirectoryError
  case notFindLogURL
  case lastLogNameError(logName: String)
  case pathToDataError
  case imageKeyParseError
}

예상치 못한 흐름이 발생했을 때에 throw문을 통해 에러를 발생시켜 일반적인 흐름이 계속될 수 없다는 것을 알릴 수 있다. 아래 코뜨는 해당 이름의 로그가 잘못되었다는 것을 알리는 에러를 발생시킨다.

throw LogViewError.lastLogNameError(logName: "로그파일1")

에러 처리

함수가 에러를 발생시킬 때, 에런느 프로그램의 흐름을 바꾼다. 때문에 그 코드의 위치를 빠르게 파악하는 것이 중요하다. 이는 try 키워드를 사용한다. Swift에는 에러를 처리하는 네 가지 방법이 있다.

  • 에러가 발생한 함수에서 리턴 값으로 에러를 반환해 해당 함수를 호출한 코드에서 에러를 처리하도록 하는 방법
  • do-catch 문을 사용
  • 옵셔널 값을 반환
  • assert를 사용해 강제로 크래쉬를 발생

함수를 사용한 에러 처리

함수, 메소드, 이니셜라이저가 에러를 발생시킬 수 있음을 알리기 위해 매개변수 뒤에 throws 키워드를 사용한다. 이 키워드가 있는 함수를 throwing function 이라고 한다.

func getLog() throws { ... }
func getLog() throws -> String { ... }

throwing function은 그 함수를 호출한 곳으로 에러를 전파한다. throwing function만이 에러를 전파할 수 있으며 throwing function가 아니라면 함수 안에서 에러를 처리해야 한다.(do-catch) 아래 코드는 예시이다.

func getLog(logFileName: String) throws { 
    guard let lastLogfileName = logFileName.dropLast(4) else { 
        throw LogViewError.lastLogNameError(logName: logFileName)
    }
}

해당 함수를 호출할 때에는 getLog(logFileName: String)이 에러를 발생할 수 있기 때문에 try 키워드와 함께 호출한다. 단순히 메소드 뿐만 아니라 이니셜라이저에서도 호출할 수 있다.

func readLog() throws { 
    try getLog(logFileName: "로그파일1")
}

struct log { 
    let logFileName: String

    init(logFileName: String) throws { 
        try getLog(logFileName:logFileName) 
        self.logFileName = logFileName
    }
}

do-catch를 통한 에러 처리

do-catch 구문은 코드 블록에서 에러를 처리하기 위해 사용한다. throwing function이 아니라면 do-catch 구문에서 에러를 처리해야하고, throwing function 이라면 do-catch구문에서 처리하거나 해당 메소드를 호출한 곳에서 처리해야 한다.

do { 
    guard let documentDirectory = documentDirectory else {
    throw LogViewError.documentDirectoryError
  }

    guard let logContentsUrl = logContentsUrl,
            let lastLogUrl = logContentsUrl.first else {
    throw LogViewError.notFindLogURL
  }

    /// 기타 로직
} catch let error as LogViewError { 
    switch error {
    case .documentDirectoryError:
        print("도큐먼트 경로 에러") 
    case .notFindLogURL: 
        print("url 주소가 잘못됨")
    } catch { 
        print("다른 에러")
    }
}

에러를 옵셔널 값으로 변환하기(try?)

try? 표현에서 에러가 발생한다면 그 결과는 nil이 된다.

/// 접근이 실패하면 nil값을 반환한다. 
let data = try? fetchDataFromUrl(url: Url) { return data }    

그 외에 …

  • try! 키워드는 에러를 발생하지 않을 것이라 확신이 있을 경우 사용한다.
  • throw 등이 실행되어 코드 블록이 종료되기 전에 defer 키워드로 필요한 정리를 할 수 있다.

참고

공식 문서로 공부하는 Swift (16) - 에러 처리