스위프트에서 오류는 Error라는 빈 프로토콜을 준수하는 타입의 값을 통해 표현된다. 주로 열거형을 사용하고 associatedValue를 통해 부가적인 정보도 제공할 수 있다.
enum NetworkError: Error {
case dataNil
case statusCodeError
case decodeError
}
위처럼 오류의 종류를 미리 예상한 다음 오류 때문에 다음에 행할 동작이 정상적으로 진행되지 않을 때 오류를 던져(throw error)주면 된다. 이때 throw 구문을 사용한다.
// 함수, 메서드, 이니셜라이저 매개변수 뒤에 throws 키워드를 사용
// 함수나 메서드의 타입에 영향을 미친다.
// throws를 포함한 아래 함수는 재정의 불가, 반대로 어떤 함수를 throws로 재정의는 가능
func canThrowErrors() throws -> String
위의 throws 함수를 호출하면 동작 도중 오류가 발생할 때 자신을 호출한 코드에 오류를 던져준다. 이걸 try를 사용해서 해당 함수를 실행하면 되는데, 이렇게 하면 함수를 호출은 하지만 어떤 처리도 할 수 없다. 그래서 아래 세 가지 방법을 사용.
do {
try 오류 발생 가능 코드
오류가 발생하지 않으면 실행할 코드
} catch 오류 패턴 1 {
처리코드
} catch 오류 패턴 2 where 추가 조건 {
처리코드
}
옵셔널 값으로 처리
try? 를 사용하여 옵셔널 값으로 변환하여, 오류를 던지는 해당 코드의 반환 값을 nil로 하는 것. 값을 반환하더라도 옵셔널 값이다. 옵셔널 바인딩을 이용해서 데이터를 디스크에서 가져오고 없으면 네트워크에서 가져오는 등의 코드를 작성할 수 있다.
오류가 생기지 않을 거라고 확신
try! 를 사용한다. 실제 오류가 발생하면 런타임 오류로 크래쉬가 난다.
'매개변수로 전달 받은 함수'가 오류를 던진다는 것을 나타낼 수 있다. 따라서 하나 이상의 오류 발생 가능한 함수를 매개변수로 전달받아야 한다. 다시 던지기 함수는 스스로 오류를 던지지 못한다. 그래서 직접적으로 throw 구문을 사용할 수 없다.
// 매개변수로 받는다.
func someFunction(callback: () throw -> Void) rethrows {
// 오류를 다시 던질 뿐 따로 처리하지는 않는다. 그저 try
try callback()
}
하지만 do-catch 구문을 사용해, (do에서) 다시 던지거나 catch절 내부에서 throw 구문을 작성해 오류를 던질 수 있다. 반면 매개변수로 전달되지 않은 오류함수는 catch에서 throw를 사용할 수 없다.
func someFunction(callback: () throw -> Void) rethrows {
do {
try callback()
} catch {
throw AnotherError.justError
}
}
프로토콜 요구사항에서 다시 던지기 메서드를 던지기 메서드를 구현한다고 해도 요구사항을 충족시킬 수 없다. 하지만 반대는 가능하다.
현재 코드 블록을 나가기 전에 꼭 실행해야 하는 코드를 작성할 수 있다. 마무리 작업에 많이 상용된다. 오류처리에 많이 사용되지만 함수, 메서드, 반복문, 조건문 등등 보통의 코드 블록 어디에서든 사용할 수 있다.