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-catch
statement λ₯Ό μ΄μ©ν΄ μ£Όλ³ μ½λκ° μλ¬λ₯Ό μ§μ μ²λ¦¬νλ€. - ν¨μλ₯Ό νΈμΆν μ½λμ context κ° λ€μ μλ¬λ₯Ό
throw
:throws
keyword λ₯Ό μ΄μ©ν΄ μλ¬λ₯Ό λ μλ‘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 νλ κ²λ κ°λ₯νλ€.
λͺ¨λ
catch
clause λ λ³λλ‘ μλ¬ μμλ₯Ό μ μνμ§ μμΌλ©΄, 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.
catch
clauses λ do clause κ° throw ν μ μλλͺ¨λ μλ¬λ₯Ό μ²λ¦¬ν νμλ μλ€
. λ§μ½, catch clauses κ° μλ¬λ₯Ό μ²λ¦¬νμ§ μμΌλ©΄,μλ¬λ μ£Όλ³ scope λ‘ propagation
λλ€. μ΄λ κ²propagation
λ μ½λλ λ°λμ μ΄κ²μ λλ¬μΌ βscopeβ μ μν΄ μ²λ¦¬`λμ΄μΌνλ€.
Nonthrowing Functions
: λ°λμdo-catch
statement λ‘ κ°μΈ μλ¬λ₯Ό μ²λ¦¬ν΄μΌνλ€.Throwing Functions
:do-catch
statement λ‘ κ°μΈκ±°λ, μλ¬λ₯Ό λμ Έ μ¬λ¦¬κ³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.