에러의 표시와 발생
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
에러 처리
- 에러가 발생한 함수에서 리턴값으로 에러를 반환해 해당 함수를 호출한 코드에서 에러를 처리하도록 하는 방법
- do-catch 구문을 사용하는 방법
- 옵셔널 값을 반환하는 방법
- assert를 사용해 강제로 크래쉬를 발생시키는 방법
에러를 발생시키는 함수 사용하기
어떤 함수, 메소드 혹은 생성자가 에러를 발생시킬 수 있다는 것을 알리기 위해 throw 키워드를 함수 선언부의 파라미터 뒤에 붙일 수 있음
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing \\(name)")
}
}
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
do-catch를 이용해 에러를 처리하기
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch {
statements
}
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
print("Success! Yum.")
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional \\(coinsNeeded) coins.")
} catch {
print("Unexpected error: \\(error).")
}
// Prints "Insufficient funds. Please insert an additional 2 coins."
func nourish(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
// 모든 VendingMachineError 구분을 위해 is를 사용
print("Invalid selection, out of stock, or not enough money.")
}
}
do {
try nourish(with: "Beet-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: \\(error)")
// 여기에서 처럼 catch를 그냥 if-else에서 else 같이 사용 가능
}
// Prints "Invalid selection, out of stock, or not enough money."
에러를 옵셔널 값으로 변환하기
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
에러 발생을 중지하기
- 함수나 메소드에서 에러가 발생되지 않을 것이라고 확신하는 경우 try!를 사용할 수 있음
- let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
정리 액션 기술
- defer 구문을 이용해 함수가 종료 된 후 파일 스트림을 닫거나, 사용했던 자원을 해지 하는 등의 일을 할 수 있음
- defer가 여러개가 있는 경우 가장 마지막 줄부터 실행 됩니다. 즉 bottom-up 순으로 실행
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file) // block이 끝나기 직전에 실행, 주로 자원 해제나 정지에 사용
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
반응형
'⌨️ Language > swift' 카테고리의 다른 글
[Swift] 제네릭 (0) | 2024.04.02 |
---|---|
[Swift] 프로토콜 (0) | 2024.03.29 |
[Swift] 옵셔널 체이닝 (0) | 2024.03.26 |
[Swift] 초기화 (1) | 2024.03.25 |
[Swift] 상속 (0) | 2024.03.22 |
댓글