enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
try try? try! ํค์๋๋ฅผ ์ฌ์ฉ.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)")
    }
}
์ด๋ ๊ฒ ์๋ฌ๋ฅผ ๋ฟ์ ์ ์๋ ํจ์๋ try ํค์๋๋ฅผ ๋ถ์ฌ์ ํธ์ถํ๋ค.
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)
}
// ์คํจํ  ์ ์๋ ๊ตฌ๋ฌธ์ init ์์ ๋ถ๋ฅด๋ฉด, init ์ญ์ throws Error.
struct PurchasedSnack {
    let name: String
    init(name: String, vendingMachine: VendingMachine) throws {
        try vendingMachine.vend(itemNamed: name)
        self.name = name
    }
}
do {
    // ์๋ฌ๊ฐ ๋ฐ์ํ  ์ ์๋ ๊ตฌ๋ฌธ
    try ํจ์
} catch pattern1 {
    // pattern1 ์๋ฌ๊ฐ ๋ฐ์ ํ์ ๋ ์ฒ๋ฆฌ ๊ตฌ๋ฌธ
} catch pattern2 where condition {
    // ํน์  condition์์ pattern2 ์๋ฌ๊ฐ ๋ฐ์ ํ์ ๋ ์ฒ๋ฆฌ ๊ตฌ๋ฌธ
} catch pattern3, pattern4, where condition {
    // ....
} catch {
    // ์์์ ์กํ์ง ์์ ๋ชจ๋  ์๋ฌ ์ก๋๋ค.
    // error ๋ผ๋ ์ง์ญ ์์๋ก ์๋ฌ๋ฅผ ๋ฐ์ธ๋ฉ ํด์ค๋ค.
    print(error)
}
func nourish(with item: String) throws {
    do {
        try vendingMachine.vend(itemNamed: item)
    } catch is VendingMachineError {
        print("Couldn't buy that from the vending machine.")
    }
}
do {
    try nourish(with: "Beet-Flavored Chips")
} catch {
    print("Unexpected non-vending-machine-related error: \(error)")
}
// Prints "Couldn't buy that from the vending machine."
try? ์ ์ฌ์ฉํด์ ์๋ฌ๊ฐ ๋ฐ์ํ  ์ ์๋ ํจ์๋ฅผ ํธ์ถํ๋ค.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
}
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
deferdefer ๊ตฌ๋ฌธ ์์ deinit ์ฒ๋ผ ํ์ฌ ๊ตฌ๋ฌธ์ด ๋๋  ๋ ์ ๋ฆฌํด์ผํ๋ ์ฝ๋๋ฅผ ๋ฃ์ด์ ์ฌ์ฉํ๋ฉด ๋๋ค.func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // Work with the file.
        }
        // close(file) is called here, at the end of the scope.
    }
}
func deferTest() -> String {
    defer {
        print("first defer start")
        defer {
            print("second defer start")
            defer {
                print("third defer start")
                print("third defer end")
            }
            print("second defer end")
        }
        print("first defer end")
    }
    
    print("out of defer")
    
    return "str"
}
print(deferTest())
// ์คํ ๊ฒฐ๊ณผ
out of defer
first defer start
first defer end
second defer start
second defer end
third defer start
third defer end
str
์ถ์ฒ
https://bbiguduk.gitbook.io/swift/language-guide-1/error-handling
https://babbab2.tistory.com/80