스위프트에서 에러는 Error 프로토콜을 따르는 타입의 값으로 표현된다.
다음과 같이 열거형으로 오류의 종류를 표현하는 것이 가장 일반적이다.
enum PhoneError: Error {
case unknown
case batteryLow(batteryLevel: Int)
}
만약 배터리가 부족할 때 오류를 발생시키고 싶다면, throw를 사용하여 오류를 발생시킬 수 있다.
throw PhoneError.batteryLow(batteryLevel: 20)
-> 오류 발생
func checkPhoneBatteryStatus(batteryLevel: Int) throws -> String {
guard batteryLevel != -1 else { throw PhoneError.unknown }
guard batteryLevel >= 20 else { throw PhoneError.batteryLow(batteryLevel: 20) }
return "배터리 상태가 정상입니다."
// > guard 조건에 모두 걸리지 않으면 문자열 반환됨
}
guard 문은 false 일 때 else 구문이 실행되고 함수가 조기종료되기 때문에 batteryLevel이 -1 이거나 20보다 작다면 else 구문이 실행되고, throw 에러를 던진 후 함수가 종료된다
do {
try 오류 발생 가능 코드
} catch 오류 패턴 {
처리 코드
}
do {
try checkPhoneBatteryStatus(batteryLevel: -1)
} catch PhoneError.unknown {
print("알 수 없는 에러입니다.")
} catch PhoneError.batteryLow(let batteryLevel) {
print("배터리 전원 부족, 남은 배터리 : \(batteryLevel)%")
} catch {
print("그 외 오류 발생 : \(error)")
}
마지막 catch 문은 unknown 에러도, batteryLow 에러도 아닌 경우 실행되는 구문이다. 오류의 종류를 명시하지 않아도 코드블럭을 생성하면 블럭 내부에 암시적으로 error 라는 이름의 지역상수가 오류 내용으로 들어오게 된다.
try? 표현을 통해 동작하던 코드가 오류를 던지면 그 코드의 반환값은 nil이 된다
let status = try? checkPhoneBatteryStatus(batteryLevel: -1)
print(status)
이 때 만약 함수가 오류를 발생하지 않는다면
옵셔널 값이 출력된다.
let status2 = try! checkPhoneBatteryStatus(batteryLevel: 40)
print(status2)
만약 오류가 발생한다면
프로그램이 강제로 종료된다.