정의
- 오류처리는 프로그램에서 발생한 에러를 받고 대응하는 과정입니다.
- Swift에서 오류를 표기하는 방법으로 Error 프로토콜과 열거형을 사용합니다.
오류 표현
enum 오류종류이름: Error {
case 종류1
case 종류2
case 종류3
...
}
오류처리 예제
오류처리 생성
- 자판기가 일으킬 수 있는 오류사항을 표현한 VendingMachineError 열거형
- 오류사항은 다음과 같습니다.
1, 금액 투입의 오류
2, 잔액 부족
3, 품절
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
}
메서드 생성 1 : 돈을 받는 메서드
- 메서드 안에서 오류가 발생했다고 자신을 호출시킨 메서드나 해당 블록에 throw를 사용하여 오류를 발생시킵니다.
- 메서드의 이름 옆에 throws 키워드를 작성해 오류가 발생할 여지가 있음을 표현합니다.
- 오류가 없으면 받은 금액을 출력하는 메시지를 보내고, 돈이 0원 이하면 오류를 발생시키도록 메서드를 구현했습니다.
func receiveMoney(_ money: Int) throws {
// 입력한 돈이 0이하면 오류를 던집니다
guard money > 0 else {
throw VendingMachineError.invalidInput
}
// 오류가 없으면 정상처리를 합니다
self.deposited += money
print("\(money)원 받음")
}
메서드 생성 2 : 물건 판매 메서드
- 첫 번째 메서드와 마찬가지로 throws 키워드를 명시해 오류가 발생할 수 있음을 표현합니다.
- 물건의 수량, 금액, 요구 수량에 해당하는 오류를 처리하는 코드들을 구현하고, 오류가 없으면 정상 처리하도록 코드를 작성합니다.
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?
오류처리 사용
- 오류를 내포하고있는 메서드를 사용할 때에는 반드시 try를 사용해 호출해야 합니다.
- 오류 발생에 대비해 do-catch문을 함께 사용합니다.
try
- 가장 정석적인 방법으로 모든 오류 종류에 대응할 수 있습니다.
- 먼저 do 블록 안에 try 구문을 작성하고, catch로 구문을 마무리해줍니다.
- do 블록 안에 구문에서 오류가 발생해,
함수가 던져지면(throw) catch 뒤에 오는 오류 종류와 일치하는 구문을 실행합니다.
do {
try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
print("수량이 부족합니다")
}
switch case문을 이용한 try
- 정석적인 try 문과 동일합니다.
- switch case문을 이용해 오류 종류에 대해 분류할 수 있습니다.
- 주석처리되어있는 (let error) 상수 부분을 통해 catch 구문으로 상수를 암시적으로 보낼 수 있습니다.
- 즉, 필요에 의해서 전달 인자의 이름을 변경할 수 있습니다.
do {
try machine.receiveMoney(300)
} catch /*(let error)*/ {
switch error {
case VendingMachineError.invalidInput:
print("입력이 잘못되었습니다")
case VendingMachineError.insufficientFunds(let moneyNeeded):
print("\(moneyNeeded)원이 부족합니다")
case VendingMachineError.outOfStock:
print("수량이 부족합니다")
default:
print("알수없는 오류 \(error)")
}
}
오류 분류 생략
- 케이스별로 오류처리 분류를 할 필요가 없다면, 다음과 같이 catch내부 구문을 간략하게 작성할 수 있습니다.
do {
result = try machine.vend(numberOfItems: 4)
} catch {
print(error)
}
try?
- 별도의 오류처리 결과를 통보받지 않고, 오류가 발생했으면 결괏값을 nil로 돌려받을 수 있습니다.
- 정상 동작 후에는 옵셔널 타입으로 정상 반환 값을 돌려받습니다.
- do catch를 쓰지 않고 오류를 던져주는 메서드를 호출해 nil값을 받거나 옵셔널 타입의 정상 결괏값을 받습니다.
정상동작
result = try? machine.vend(numberOfItems: 2)
print(result as Any) // Optional("2개 제공함")
오류발생
result = try? machine.vend(numberOfItems: 2)
print(result as Any) // nil
try!
- 오류가 발생하지 않을 것이라는 확신을 가질 때 사용합니다.
- try! 를 사용하여 정상 동작 후에 바로 결과값을 돌려받습니다.
- 오류가 발생하면 런타임 오류가 발생하여 동작이 중지됩니다.
- 정상동작 후에는 일반 타입의 정상 반환 값을 돌려받습니다.
정상동작
result = try! machine.vend(numberOfItems: 1)
print(result as Any) // 1개 제공함
오류발생
result = try! machine.vend(numberOfItems: 1) // 런타임 오류 프로그램 동작 중지
내용 출처
https://www.youtube.com/watch?v=l0fGtNnNsJg&list=PLz8NH7YHUj_ZmlgcSETF51Z9GSSU6Uioy&index=28
'iOS > Swift 문법 심화 학습' 카테고리의 다른 글
제네릭 [ Generic ] (0) | 2022.02.08 |
---|---|
고차함수 [ map, filter, reduce ] (0) | 2022.02.07 |
열거형 [ enum ] (0) | 2022.02.03 |
클래스 [ Class ] (0) | 2022.02.03 |
구조체 [ Struct ] (0) | 2022.02.03 |
댓글