Swift Error Handling
Error handling in Swift interoperates with error handling patterns that use the NSError class in Cocoa and Objective-C.
1. Representing and Throwing Errors π©βπ»
Swift μ μλ¬ μ²λ¦¬λ Cocoa μ Objective-C μμ 'NSError class'λ₯Ό μ¬μ©νλ μλ¬ μ²λ¦¬ ν¨ν΄κ³Ό μνΈ μ΄μ© λλ€.
Handling Cocoa Errors in Swift
Swift μμ μλ¬λ Error protocol μ λ°λ₯΄λ Types μ κ°μΌλ‘ ννλλ€. κ·Έλ¬κΈ° μν΄μ Error protocol μ μ±ννλλ‘ ν΄μΌνλ€.
Swift μ Enumerations λ μ°κ΄λ Error conditions λ₯Ό κ·Έλ£Ήννλλ° μ ν©νλ€.
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
μλ¬λ₯Ό λμ§κΈ° μν΄ throw statement λ₯Ό μ¬μ©ν μ μλ€. λ€μ μμ λ μνκΈ°κ° λμ μ΄ 5κ° λ νμνλ€λ μλ¬λ₯Ό λ°μμν€λ κ²½μ°λ€.
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
2. Handling Errors π©βπ»
μλ¬κ° λ°μνλ©΄ μλ¬λ μ£Όλ³ μ½λμ μν΄ λ¬Έμ λ₯Ό μμ νκ±°λ, λμ μ κ·Ό λ°©μμ μλνκ±°λ, μ¬μ©μμκ² μλ¦Ό λ±μ λ°©λ²μ ν΅ν΄
λ°λμ μ²λ¦¬λμ΄μΌνλ€.
ν¨μμμ μλ¬κ° λ°μνλ©΄ νλ‘κ·Έλ¨μ νλ¦μ΄ λ³κ²½λλ―λ‘, μ½λμμ μλ¬κ° λ°μν μμΉλ₯Ό λΉ λ₯΄κ² μ°Ύλ κ²μ΄ λ§€μ° μ€μνλ€. μ΄λ₯Ό μν΄
Functions, Methods, Initializers λ₯Ό νΈμΆνλ μ½λ μμ try(or try? or try!) keyword λ₯Ό μμ±ν΄
try expression μΌλ‘ μ½λλ₯Ό μμ±νλ€.
Swift μ μλ¬ μ²λ¦¬λ λ€λ₯Έ μΈμ΄μ
try-catch & throwμ μ μ¬νλ€. νμ§λ§ Objective-C λ₯Ό ν¬ν¨ν λ§μ μΈμ΄μ λ¬λ¦¬ Swift μ μλ¬ μ²λ¦¬λ κ³μ° λΉμ©μ΄ λ§μ΄ λλCall Stack ν΄μ (unwinding)μ ν¬ν¨νμ§ μλλ€.
Swift μthrow statementμ μ±λ₯ νΉμ±μreturn statementμ μ μ¬νλ€.
1. Propagating Errors Using Throwing Functions
μλ¬λ₯Ό throwν μ μλ Functions, Methods, Initializersλ₯Ό μν΄ ν¨μμ parameters λ€μ throws keyword
λ₯Ό μμ±νλ©°, μ΄λ° ν¨μλ₯Ό Throwing FunctionsλΌ νλ€. Throwing Functions λ‘ μμ±νλ©΄ λ°μν μλ¬λ₯Ό μ§μ μ²λ¦¬νμ§ μκ³
throw ν΄μ νΈμΆν μ½λμ μ£Όλ³ μ½λκ° μλ¬λ₯Ό μ²λ¦¬νλλ‘ ν μ μλ€.
Syntax
func canThrowErrors() throws -> String
Throwing Functions λ§ μλ¬λ₯Ό throwingν μ μλ€.Nonthrowing Functions μ λ°μν λͺ¨λ μλ¬λ₯Ό ν¨μ μμμ μ²λ¦¬ν΄μΌνλ€.
Throwing Functions, Throwing Initializers λ₯Ό νΈμΆν λλ μλ¬κ° μ²λ¦¬λμ§ μκ³ thorw λ μ μμμ λΆλͺ
ν ν΄μΌνλ€.
μ¦, tryλ₯Ό μ΄μ©ν΄ ν¨μλ₯Ό νΈμΆνλ©°, ν¨μλ₯Ό νΈμΆν μ½λμ μ£Όλ³ μ½λμ μν΄ μλ¬κ° μ²λ¦¬λκ±°λ, κ³μν΄μ propagation ν΄μΌνλ€.
- ν¨μλ₯Ό νΈμΆν μ½λμ μ£Όλ³ μ½λκ° μλ¬λ₯Ό μ²λ¦¬ :
do-catchstatement λ₯Ό μ΄μ©ν΄ μ£Όλ³ μ½λκ° μλ¬λ₯Ό μ§μ μ²λ¦¬νλ€. - ν¨μλ₯Ό νΈμΆν μ½λμ context κ° λ€μ μλ¬λ₯Ό
throw:throwskeyword λ₯Ό μ΄μ©ν΄ μλ¬λ₯Ό λ μλ‘throwμ²λ¦¬νλ€.
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)")
}
}
μνκΈ°μ vend(itemNamed:) λ©μλλ μνμ΄ μ‘΄μ¬νλμ§ νμΈνκ³ , μ¬κ³ λ₯Ό νμΈν ν, μΆ©λΆν λμ λ£μλμ§ νμΈν΄ μνμ
μ 곡νλ€. λ§μ½, μ΄λμλ μλ¬κ° λ°μν κ²½μ° λ©μλλ μ¦μ μ’
λ£λκ³ μλ¬λ₯Ό throwνλ€.
let favoriteSnacks = [
"Alice": "Chips",
"Queen": "Licorice",
"Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
vend(itemNamed:) λ©μλκ° Throwing Functionsμ΄κΈ° λλ¬Έμ try keyword λ₯Ό μ¬μ©ν΄ νΈμΆν΄μΌνλ€. κ·Έλ¦¬κ³ μ΄κ²μ
νΈμΆν μ½λμ μ£Όλ³ μ½λμ μν΄ μλ¬κ° μ²λ¦¬λκ±°λ κ³μ propagation ν΄μΌνλ€.
μ½λλ λ¨μν try vendingMachine.vend(itemNamed: snackName)λ₯Ό μ΄μ©ν΄ νΈμΆλ§ νκ³ μμΌλ―λ‘ μλ¬λ λ°λμ λ€μ μλ‘
throw λμ΄μΌ νλ€. λ°λΌμ throws keyword λ₯Ό μΆκ°ν΄ buyFavoriteSnack(person:vendingMachine:) ν¨μ
μμ Throwing Functionsλ‘ λ§λ€μ΄μΌνλ€.
Propagating Errors Using Throwing Initializers
Throwing Initializers μμ μλ¬λ₯Ό propagation ν μ μμΌλ©°, λ°©λ²μ Throwing Functionsμ κ°λ€.
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
2. Handling Errors Using Do-Catch
Syntax
do {
try expression
statements
} catch pattern 1(let errorConstant) {
statements
} catch pattern 2 where condition {
statements
} catch pattern 3, pattern 4 where condition {
statements
} catch {
statements
}
do-catch statement λ μ½λ λΈλμΌλ‘ μλ¬λ₯Ό μ²λ¦¬νλ€. do clause μμ μλ¬κ° thrown λλ©΄, catch clauses μμ μΌμΉνλ
μλ¬λ₯Ό μ²λ¦¬νλ€.
pattern μ΄ μΌμΉνκ±°λ, pattern κ³Ό condition μ΄ μΌμΉν λ trigger λλ©° μλ¬΄λ° pattern λ μΆκ°νμ§ μμΌλ©΄
λλ¨Έμ§ λͺ¨λ μλ¬λ₯Ό μ²λ¦¬νλ€.
pattern μ catch λ€μμ μμ±νλ©°, condition μ pattern λ€μμ 'where' λ₯Ό μ΄μ©ν΄ μΆκ°νλ€. λν , λ₯Ό μ΄μ©ν΄
Multiple Patterns λ₯Ό νλμ catch clause μ μ°κ²°νκ±°λ catch is λ₯Ό μ΄μ©ν΄ μ¬λ¬ cases λ₯Ό νλμ
catch μμ μ²λ¦¬ν μ μλ€. λν Switch Value Bindings μ κ°μ΄ catch clause
λ΄λΆ context μμ μ¬μ©ν κ°μ binding νλ κ²λ κ°λ₯νλ€.
λͺ¨λ
catchclause λ λ³λλ‘ μλ¬ μμλ₯Ό μ μνμ§ μμΌλ©΄, default λ‘errorλ₯Όlocal constantλ‘ μ¬μ©νλ€.
1 ) do-catch examples 1
let favoriteSnacks = [
"Alice": "Chips",
"Queen": "Licorice",
"Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
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).")
}
Insufficient funds. Please insert an additional 2 coins.
catchclauses λ do clause κ° throw ν μ μλλͺ¨λ μλ¬λ₯Ό μ²λ¦¬ν νμλ μλ€. λ§μ½, catch clauses κ° μλ¬λ₯Ό μ²λ¦¬νμ§ μμΌλ©΄,μλ¬λ μ£Όλ³ scope λ‘ propagationλλ€. μ΄λ κ²propagationλ μ½λλ λ°λμ μ΄κ²μ λλ¬μΌ βscopeβ μ μν΄ μ²λ¦¬`λμ΄μΌνλ€.
Nonthrowing Functions: λ°λμdo-catchstatement λ‘ κ°μΈ μλ¬λ₯Ό μ²λ¦¬ν΄μΌνλ€.Throwing Functions:do-catchstatement λ‘ κ°μΈκ±°λ, μλ¬λ₯Ό λμ Έ μ¬λ¦¬κ³callerκ° μλ¬λ₯Ό μ²λ¦¬ν΄μΌνλ€.λ§μ½ μλ¬λ₯Ό μ΄λμλ μ²λ¦¬νμ§ μμ κ²½μ°,
Runtime Errorκ° λ°μλλ€. λ°λΌμ Throwing Functions λ do-catch κ° λͺ¨λ μλ¬λ₯Ό μ²λ¦¬ν νμ μμ΄ μλ‘ throw ν μ μμ§λ§ Nonthrowing Functions λ λ°λμ do-catch κ° λͺ¨λ μλ¬λ₯Ό μ²λ¦¬ν΄μΌ νλ€.
2 ) do-catch examples 2
catch isλ₯Ό μ΄μ©ν΄ μ°κ΄λ μλ¬λ₯Ό ν λ²μ μ²λ¦¬ν μ μλ€.
func buySnack(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
print("Couldn't buy that from the vending machine.")
}
}
do {
try buySnack(with: "Beat-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: \(error)")
}
Couldn't buy that from the vending machine.
μ΄ κ²½μ°
VendingMachineErrorκ° λ°μνλ©΄catch is VendingMachineErrorμ μν΄ μ²λ¦¬κ° λκ³ ,κ·Έ μΈ μλ¬κ° λ°μνλ©΄throwsλμ΄callerμ μν΄ μ²λ¦¬λλ€.
3 ) do-catch examples 3
λλ catch is λμ μ°κ΄λ μλ¬λ₯Ό νμν λ§νΌ , λ₯Ό μ΄μ©ν΄ λμ΄ν΄ μ²λ¦¬ν μ μλ€.
func buySnack(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch VendingMachineError.invalidSelection,
VendingMachineError.insufficientFunds,
VendingMachineError.outOfStock {
print("""
Couldn't buy that from the vending machine
because of invalid selection, out of stock, or not enough money.
""")
}
}
do {
try buySnack(with: "Beat-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: \(error)")
}
Couldn't buy that from the vending machine
because of invalid selection, out of stock, or not enough money.
3. Converting Errors to Optional Values
Optional Chaining always returns Optional Types μ λ€μ λ μ¬λ €λ³΄μ. Optional Chainingμ ?μ μ΄μ©ν΄
Instance λλ Value κ° μ‘΄μ¬νμ§ μλ κ²½μ°μλ λ³λμ μλ¬ μ²λ¦¬ μμ΄ μ½λλ₯Ό κ°κ²°νκ² μ²λ¦¬νλ€. κ²°κ³Όλ₯Ό νμ Optioanlλ‘
Wrapping νκ³ μλ¬κ° λ°μνλ©΄ nilμ λ΄μ λ°ννκΈ° λλ¬Έμ΄λ€.
Optional Chaining κ³Ό λ§μ°¬κ°μ§λ‘ Throwing Functions μμ try λμ try?λ₯Ό μ΄μ©νλ©΄ κ²°κ³Όλ₯Ό νμ Optionalλ‘
Wrapping νλλ‘ νλ€. κ·Έλ¬λ©΄ Optional Chainingμ ν λμ λ§μ°¬κ°μ§λ‘ μΌλ° μ½λλ₯Ό μμ±νλ― μ²λ¦¬ν μ μλ€.
try?λ₯Ό μ¬μ©ν¨μΌλ‘μ¨ μ»λ μ₯μ μ λͺ¨λ μλ¬λ₯Ό κ°μ λ°©μμΌλ‘ μ²λ¦¬νλ κ²½μ° do-catch μμ΄ μ§§κ³ κ°κ²°ν μ½λλ‘ μμ±ν μ μλ€λ κ²μ΄κ³ ,
λ¨μ μ λͺ¨λ μλ¬λ₯Ό κ°μ λ°©μμΌλ‘ μ²λ¦¬νλ―λ‘ cases λ³λ‘ μμΈν μλ¬ μ²λ¦¬λ₯Ό νλ κ²μ΄ λΆκ°λ₯νλ€λ κ²μ΄λ€.
try?λOptional Chainingμ?μ λ§μ°¬κ°μ§λ‘ νμ Optional Types λ₯Ό λ°ννλ€.try!λOptional Chainingμ!μ λ§μ°¬κ°μ§λ‘ νμ λ°νκ°μ Forced Unwrapping νλ€.
enum SomeError: Error {
case zero
}
μλ 3κ°μ μΌμ΄μ€λ λͺ¨λ λμΌν μλμ νλ€.
1 ) Optional Functions
throwsλ₯Ό μ¬μ©νμ§ μκ³ ν¨μμ return type μ체λ₯Ό Optionalλ‘ λ§λ€κ³ , μλ¬ λ°μ 쑰건μ λν΄ λͺ
μμ μΌλ‘ nilμ return
μμΌ λ€μκ³Ό κ°μ΄ μλμν¬ μ μλ€.
func someOptionalFunction(_ input: Int) -> Int? {
if input == 0 {
return nil
} else {
return input
}
}
let x: Int? = someOptionalFunction(0)
print(x as Any) // nil
let y: Int? = someOptionalFunction(1)
print(y as Any) // Optional(1)
νμ§λ§ μ μΌμ΄μ€μ κ²½μ° LBYL(Look Before You Leap) λ°©μμΌλ‘, μμμΉ λͺ»ν μλ¬λ‘ μΈν΄ Runtime Errorκ° λ°μλ μ μλ€.
2 ) Throwing Functions with try
do-catchμ tryλ₯Ό μ¬μ©ν΄ μλ¬λ₯Ό μ²λ¦¬ν κ²μ΄κΈ° λλ¬Έμ λ μ΄μ return types κ° Int?μΌ νμκ° μλ€.
return types λ₯Ό Intλ‘ λ°κΎΈλλ‘νμ. μ μ ν λ€μ μ€λͺ
νκ² μ§λ§, Optional Wrapping μ΄ νμνλ©΄ λ¨μ§
try? keyword λ₯Ό μ¬μ©νκΈ°λ§ νλ©΄ λλ€.
func someThrowingFunction(_ input: Int) throws -> Int {
if input == 0 {
throw SomeError.zero
} else {
return input
}
}
μ΄μ LBYL λ°©μ λμ EAFP(Easier to Ask for Forgiveness than Permission) λ°©μμΌλ‘ μ½λλ₯Ό μμ±ν
μ μλ€. μ΄λ ν¨μκ° throwν μλ¬λ λ°λμ λ€μ throw ν΄ propagation νκ±°λ do-catchλ₯Ό μ΄μ©ν΄ μ²λ¦¬ν΄μΌνλ€.
let v: Int?
do {
v = try someThrowingFunction(0)
} catch {
v = nil
}
print(v as Any) // nil
let w: Int?
do {
w = try someThrowingFunction(1)
} catch {
w = nil
}
print(w as Any) // Optional(1)
let x: Int
do {
x = try someThrowingFunction(2)
} catch {
x = -1
}
print(x) // 2 (Not Optional!!)
LBYL λ°©μκ³Ό λ¬λ¦¬ μμμΉ λͺ»ν μλ¬λ λͺ¨λ catch clause λ₯Ό ν΅ν΄ μ²λ¦¬ν μ μμΌλ―λ‘ Runtime Error λ°μμ λ§μ μ μκ²λμλ€.
νμ§λ§ νΉλ³νκ² μλ¬λ₯Ό ꡬλΆν΄ μ²λ¦¬ν νμκ° μμ κ²½μ° μ λ°©μμ μ½λμ νλ¦μ΄ λΆλ¦¬λμ΄ κ°λ
μ±μ΄ μ’μ§ λͺ»ν
λ¬Έμ κ° μ‘΄μ¬νλ€.
3 ) Throwing Functions with try?
try? keyword λ₯Ό μ¬μ©νλ©΄ μλ¬λ₯Ό Optionalλ‘ Wrapping ν΄ EAFP λ°©μμΌλ‘ μ½λλ₯Ό μμ±νλ©΄μ μ κ°λ
μ± λ¬Έμ λ ν΄κ²°ν μ μλ€.
let p = try? someThrowingFunction(0)
print(p as Any) // nil
let q = try? someThrowingFunction(1)
print(q as Any) // Optional(1)
μλ₯Ό λ€μ΄ fetchμ κ°μ ν¨μλ try?λ₯Ό μ΄μ©ν΄ λ€μκ³Ό κ°μ΄ κ°κ²°νκ² μμ±ν μ μλ€.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
4. Disabling Error Propagation
dot Syntaxλ₯Ό μ΄μ©ν λ μ°λ¦¬λ 3κ°μ§ λ°©λ²μΌλ‘ μ κ·Όν μ μμλ€. Optional Chaining μ νμ§ μλ . κ³Ό
Optional Chaining μ νλ ?., λ§μ§λ§μΌλ‘ Forced Unwrapping μ νλ !.μ΄λ€.
tryλ λ§μ°¬κ°μ§λ‘ try, try?, try! 3κ°μ§ Syntax κ° μ‘΄μ¬νλ€. μμμ try λμ try?λ₯Ό μ¬μ©ν΄
Optional or nil λ₯Ό λ°ννλλ‘ Throwing Functions νΈμΆμ λ€λ£¨λ κ²μ 보μλ€. try! μμ
Optional Chaining μ !.μ μ μ¬νλ€.
μ λλ‘ μλ¬κ° λ°μνμ§ μλλ€λ κ²μ μκ³ μλ κ²½μ°, Throwing Functions λ₯Ό νΈμΆν λ try! λ₯Ό μ΄μ©ν μ μλ€.
μ΄ κ²½μ° λ€μ λ κ°μ§κ° μλνμ§ μλλ€.
- Error Propagation
- λ°ν κ°μ Optional Wrapping
let x = try? someThrowingFunction(1)
print(x as Any) // Optional(1)
let y = try! someThrowingFunction(1)
print(y) // 1
try?λ₯Ό μ΄μ©ν νΈμΆκ³Ό λ¬λ¦¬ Unwrappedλ κ°μ μ»μ μ μλ€.
λ¨, μ΄ λ μ£Όμν΄μΌν κ²μ΄
throws -> Intκ° μλthrows -> Int?μΌ κ²½μ°func someThrowingFunction(_ input: Int) throws -> Int? { if input == 0 { throw SomeError.zero } else { return input } }
throwμ ν λ²,Int?μ ν λ² => μ΄ 2λ²μOptional Wrappingμ΄ μ΄λ£¨μ΄μ§λ€.
λ°λΌμthrowμ μν΄ Wrapping λ Optional μ ν΄μ νλλΌλ λ€μ Int? μ μν΄ Optional Wrapping λ κ°μ μ»λλ€. ν¨μκ° λ°νν κ°μ΄Optional(Optional(1))μ΄κΈ° λλ¬Έμ΄λ€.let y = try! someThrowingFunction(1) print(y) // Optional(1)
λ‘컬 κ²½λ‘μμ μ΄λ―Έμ§λ₯Ό κ°μ Έμ€λ μ½λλ₯Ό μκ°ν΄λ³΄μ.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
μ΄λ―Έμ§κ° μ‘΄μ¬ν κ²μ΄λΌ νμ νκ³ try!λ₯Ό μ¬μ©νλλ° μ΄λ―Έμ§κ° μ‘΄μ¬νμ§ μκ±°λ κ°μ Έμ€λ λ° μ€ν¨νλ€λ©΄
Runtime Error κ° λ°μνλ€. λ°λΌμ try!λ₯Ό μ¬μ©ν λλ
μ λ μλ¬κ° λ°μνμ§ μλλ€λ κ²μ λν 보μ¦μ κ°λ°μκ° ν΄μΌνλ―λ‘ μ μ€ν νλ¨μ΄ νμ
νλ€.
3. Specifying Cleanup Actions π©βπ»
Classes νμ
μ class instance μ ν λΉμ΄ ν΄μ (deallocate)λκΈ° μ§μ μ νΈμΆλ μ½λλ₯Ό μ μν μ μλ
Deinitializer λΌλ νΉλ³ν μ½λλΈλμ΄ μκ³ μ΄κ²μ deinit keyword λ₯Ό μ΄μ©ν΄ μ μνλ€.
κ·Έλ¦¬κ³ μ΄λ¬ν context λ₯Ό νμΆν λ νΈμΆλλ μ½λλ Classes λ³΄λ€ λ μμ λ¨μμΈ μ΄λ ν Block scopeμ
λν΄μλ μ μν μ μλλ° Defer StatementλΌ νλ©°, defer keyword λ₯Ό μ΄μ©ν΄ μ μνλ€.
Closures, if, switch, β¦etc μ κ°μ μ΄λ ν
Block scopeμμλ μ μν μ μλ€.
Defer Statement μμ 리μμ€λ₯Ό μ 리νκΈ° μν νΉλ³ν μ½λλ‘ λ€μκ³Ό κ°μ νΉμ§μ κ°λλ€.
μ½λ λΈλμ νμΆνκΈ° μ§μ μ νΈμΆλλ©°,throw, return, break μ κ΄κ³ μμ΄ μλνλ€.λ΄λΆμ throw, return, break λ₯Ό ν¬ν¨ν μ μλ€.- deinit κ³Ό λ¬λ¦¬
νλμ μ½λ λΈλ λ΄μ μ¬λ¬ κ°κ° μ‘΄μ¬ν μ μμΌλ©°,Stackμ μ΄μ©ν΄LIFOλ‘ μλνλ€.
func someDefer(number: Int) {
if number == 0 {
defer {
print("zero")
}
}
defer {
print("first")
}
defer {
print("second")
}
defer {
print("third")
}
}
someDefer(number: 0)
zero
third
second
first
κ·Έλ¦¬κ³ Swift λ scope μ λ§μ§λ§μ μ μλ defer λ νμ μ¦μ μ€νλλ―λ‘ deferλ₯Ό doλ‘ μμ±νλΌκ³ κ²½κ³ λ₯Ό λμ΄λ€.
λ°λΌμ μ΄ κ²½κ³ λ₯Ό λ°μλ€μ¬ μ μ½λλ₯Ό μμ νλ©΄ λ€μκ³Ό κ°λ€. μ¦, deferλ block μ μμ λλ μ€κ°μ μ μ ν scope λ₯Ό
νμΆνκΈ° μ§μ μ νΈμΆλ μ½λλ₯Ό μ μνκΈ° μν κ²μμ μ μ μλ€.
func someDefer(number: Int) {
if number == 0 {
do {
print("zero")
}
}
defer {
print("first")
}
defer {
print("second")
}
do {
print("third")
}
}
λ§μ§λ§μΌλ‘ νμΌμ λ€λ£¨λ ν¨μκ° λ¦¬μμ€λ₯Ό ν΄μ νκΈ° μν΄ deferλ₯Ό μ΄λ»κ² νμ©νλμ§ λ³΄μ.
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.
}
}
μ μ½λμμ defer λ if λΈλμ μν΄ μμΌλ―λ‘, if λΈλμ νμΆνκΈ° μ§μ μ νΈμΆλμ΄ νμΌμ λ«κ³ μλμΌλ‘ λ©λͺ¨λ¦¬ 리μμ€λ₯Ό
ν보νλ€.
(μ ν¨μμ if μΈ λ€λ₯Έ μ½λκ° μμ΄μ ν¨μκ° μ’
λ£λ λ defer κ° νΈμΆλλ κ²μ²λΌ λ³΄μΌ μ μμΌλ if λΈλμ νμΆνκΈ° μ§μ μ
νΈμΆλλ κ²μμ μ νν μ΄ν΄ν΄μΌνλ€).
Reference
- βError Handling.β The Swift Programming Language Swift 5.7. accessed Dec. 22, 2022, Swift Docs Chapter 16 - Error Handling.