오류처리는 오류 상황에 대응하고 복구하는 과정을 말한다.
Swfit에서 오류는 Error
라는 프로토콜을 준수하는 타입의 값으로 표현이 된다.
Error
프로토콜은 빈 프로토콜이지만 해당 타입이 오류처리로 이용됨을 알려준다.
enum 오류종류이름: Error {
case 종류1
case 종류2
case 종류3
//...
}
특히 열거형(enum)이 오류처리에 적합하고 자주 쓰이는데 연관 값을 통해 오류에 관한 부가적인 정보를 표현할 수 있다.
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
문제 수정하기, 다른 접근 방식을 시도하기, 사용자에게 오류를 알리기 등과 같은 처리를 통해 다음 진행을 유도해야 한다.
오류처리의 네 가지 방식
- 해당 함수를 호출한 코드로 오류 전파
do-catch
문으로 처리- optional을 이용한 처리
- 오류가 발생 부정
이러한 위치는 try를 통해 쉽게 알 수 있다.
오류는 throw 키워드로 던질 수 있는데 오류를 던질 수 있는 함수에는 throws를 붙이고 throwing function 라고 부른다.
만약 함수에 특정 리턴값이 있다면 throws 뒤에 써주면 된다.
func canThrowErrors() throws -> String
throwing function만 오류를 전파할 수 있고 아니라면 함수 내부에서 오류를 처리해줘야 한다.
func receiveMoney(_ money: Int) throws {
// 입력한 돈이 0이하면 오류를 던집니다
guard money > 0 else {
throw VendingMachineError.invalidInput
}
// 오류가 없으면 정상처리를 합니다
self.deposited += money
print("\(money)원 받음")
}
메서드가 오류를 전파하면 이 메서드를 호출한 코드는 오류를 처리하거나(do-catch) 오류를 다시 전파해야(try) 한다.
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
buyFavoriteSnack
역시 throwing function으로 vend
에서 오류가 발생하면 try로 오류를 전파하도록 처리했다.
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch pattern 3, pattern 4 where condition {
statements
} catch {
statements
}
do {
try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
print("수량이 부족합니다")
} catch {
print("Unexpected error: \(error).")
}
do
에서 오류가 발생할 수 있는 코드를 실행하고 만약 receiveMoney
가 오류를 던지면 일치하는 catch
문을 따라 오류를 처리한다.
만약 일치하는 catch 절이 없으면 마지막 catch에서 처리하게 된다.
catch로 모든 오류를 처리할 필요는 없지만 오류는 다른 구문에서라도 반드시 처리되어야 한다.
func eat(item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
print("Invalid selection, out of stock, or not enough money.")
}
}
,(컴마)
를 이용해 여러 오류를 한 catch에서 처리할 수도 있다.
try?
를 이용해 오류를 Otional 값으로 전환해서 오류를 처리할 수 있다.
별도의 결과로 처리하지 않고 오류가 발생하면 nil
을 돌려받고 정상 동작 시엔 Optional 타입으로 결과를 반환한다.
result = try? machine.vend(numberOfItems: 2) // 정상 작동
result // Optional("2개 제공함")
result = try? machine.vend(numberOfItems: 2) // 오류 발생
result // nil
오류가 발생하지 않는다는 확신이 있을 때는 try!
를 사용해 정상 동작 후 바로 결과 값을 돌려받을 수 있다.
하지만 만약 오류가 발생하면 런타임 오류가 발생해 실행 종료된다.
result = try! machine.vend(numberOfItems: 1)
result // 1개 제공함
//result = try! machine.vend(numberOfItems: 1)
// 런타임 오류 발생!