2021년 12월 31일에 공부한 내용입니다.
Error
라는 프로토콜을 준수하는 타입의 값을 통해 표현된다.Error
프로토콜은 사실상 요구사항이 없는 빈 프로토콜일 뿐이지만, 오류를 표현하기 위한 타입(주로 열거형)은 이 프로토콜을 채택한다.Error
프로토콜과 (주로) 열거형을 통해 오류를 표현한다.// 자판기 동작 오류의 종류를 표현한 VendingMachineError 열거형
enum VendingMachineError: Error {
case invalidInput
case insufficientFunds(moneyNeeded: Int) // 열거형의 연관값 참조!
case outOfStock
}
throws
를 사용하여 오류를 내포하는 함수임을 표시한다.class VendingMachine {
let itemPrice: Int = 100
var itemCount: Int = 5
var deposited: Int = 0
// 돈 받기 메서드
func receiveMoney(_ money: Int) throws {
// 입력한 돈이 0 이하면 오류를 던진다
guard money > 0 else {
throw VendingMachineError.invalidInput
}
// 오류가 없으면 정상처리를 한다
self.deposited += money
print("\(money)원 받음")
}
// 물건 팔기 메서드
func vend(numberOfItems numberOfItemsToVend: Int) throws -> String {
// 원하는 아이템의 수량이 잘못 입력되었으면 오류를 던진다
guard numberOfItemsToVend > 0 else {
throw VendingMachineError.invalidInput
}
// 구매하려는 수량보다 미리 넣어둔 돈이 적으면 오류를 던진다
guard numberOfItemsToVend * itemPrice <= deposited else {
let moneyNeeded: Int
moneyNeeded = numberOfItemsToVend * itemPrice - deposited
throw VendingMachineError.insufficientFunds(moneyNeeded: moneyNeeded)
}
// 구매하려는 수량보다 요구하는 수량이 많으면 오류를 던진다
guard itemCount >= numberOfItemsToVend else {
throw VendingMachineError.outOfStock
}
// 오류가 없으면 정상처리를 한다
let totalPrice = numberOfItemsToVend * itemPrice
self.deposited -= totalPrice
self.itemCount -= numberOfItemsToVend
return "\(numberOfItemsToVend)개 제공함"
}
}
// 자판기 인스턴스
let machine: VendingMachine = VendingMachine()
// 판매 결과를 전달받을 변수
var result: String?
throws
함수(메서드)는 try
를 사용하여 호출해야 한다.throws
함수(메서드)는 do-catch
구문을 활용하여 오류발생에 대비한다.do {
try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
print("수량이 부족합니다")
} // 입력이 잘못되었습니다
do {
try machine.receiveMoney(300)
} catch /*(let error)*/ { // error가 암시적으로 catch 구문으로 넘어온다 (생략 가능)
switch error {
case VendingMachineError.invalidInput:
print("입력이 잘못되었습니다")
case VendingMachineError.insufficientFunds(let moneyNeeded):
print("\(moneyNeeded)원이 부족합니다")
case VendingMachineError.outOfStock:
print("수량이 부족합니다")
default:
print("알수없는 오류 \(error)")
}
} // 300원 받음
// 케이스별로 오류처리 할 필요가 없으면 catch 구문 내부를 간략화해도 무방
do {
result = try machine.vend(numberOfItems: 4)
} catch {
print(error)
} // insufficientFunds(100)
// 케이스별로 오류처리를 할 필요가 없는 경우 do 구문만 써도 무방
do {
result = try machine.vend(numberOfItems: 4)
}
nil
로 돌려받을 수 있다.result = try? machine.vend(numberOfItems: 2)
result // Optional("2개 제공함")
result = try? machine.vend(numberOfItems: 2)
reuslt // nil
try!
를 사용하면 정상동작 후에 바로 결과값을 돌려받는다.result = try! machine.vend(numberOfItems: 1)
result // 1개 제공함
// result = try! machine.vend(numberOfItems: 1)