error 프로토콜과 (주로) 열거형을 통해서 오류를 표현한다.
enum VendingMachineError: Error {
case invalidInput
case insufficientFunds(moneyNeeded: Int)
case outOfStock
}
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 moneyNedded: 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: VedingMachine = VendingMachine()
var result: String?
do{
result = try machine.vend(numberOfItems: 4)
}catch{
print(error)
}
do{
result = try machine.vend(numberOfItems: 4)
}
try?는 별도의 오류 처리 결과를 통보받지 않고
오류가 발생하면 결과값을 nil로 돌려받을 수 있다.
정상 동작 후에는 옵셔널 타입으로 반환값을 돌려받는다
result = try? machine.vend(numberOfItems: 2)
result // optional
result = try? machine.vend(numberOfItems: 2)
reuslt // nil
try!
오류가 발생하지 않을 것이라는 강력한 확신을 가질 때 사용하면 정상동작 후에 바로 결과값을 돌려받는다.
오류가 발생하면 런타임 오류가 ㅂ라생하여 어플 동작이 중지된다.
result try! machine.vend(numberOfItems: 1)
result