에러처리는 프로그램의 에러 조건에서 응답하고 대응하는 프로세스이다. 일부 작업은 항상 실행을 완료하거느 유용한 출력을 생성한다고 보장되지 않는다. 작업이 실패할 경우 코드가 그에 따라서 응답하도록 에러의 원인을 이해하는 것이 유용한 경우가 많고, 이를 위해서 에러핸들링을 사용한다.
enum VendingmachineError : Error {
case invalidSelection
case insufficientFunds(coinsNeeded : Int)
case outOfStock
}
//에러가 발생하면 예상치 못한 일이 발생하여 정상적 코드흐름이 불가능함을 나타낼 수 있다.
//throw구문을 사용해서 에러를 발생시킨다.
throw VendingMachineError.insufficientFunds(coinsNeeded : 5)
//다음과 같이 에러를 명시할 수 있다.
func canThrowErrors() throws -> String {
//statement
}
//위의 메서드는 에러를 스로잉하는 함수이다.
//throwing함수는 에러를 전파만 가능하다. 던지기 선언이 되지 않은 함수에서 발생하는 모든 에러는
//모두 함수 내에서 처리되어야 한다.
struct Item {
var price : Int
var count : Int
}
class VendingMachine {
var coinDeposit = 0
func vend(itemNamed name : String) throws {
guard let item = inventory[name] else {
throws VendingMachineError.invalidSelection
}
}
}
//위에서 보는 것처럼 throw함수를 통해서 직접 에러를 스로잉 할 수 있다.
func buyFavoriteSnack(person : String, vendingMachine : VendingMachine) throws {
let snackName = snackName ?? "Candy Bar"
try vendingMachine.vend(itemNamed : snackNamed)
}
//다음과 같이 스로잉 함수를 호출할때는 앞에 try키워드를 붙여줘서 이 함수가 스로잉 함수임을 나타내준다.
do {
try expression
} catch pattern 1 {
// statement
} catch pattern 2 {
//statement
} catch pattern 3 {
//statement
}
//처리할 수 있는 에러가 무엇인지 나타내기 위해서 catch 뒤에 패턴을 작성한다.
var vendingMachine = VendingMachine()
vendingMachine.coinDeposited = 8
do {
try buyFavoriteSnack()
} catch VendingMachineError.invalidSelection {
print("invalid Selection")
} catch VendingMachineError.outOfStock {
print("Out of stock")
} catch VendingMachineError.insufficient(let coinsNeeded) {
print("insufficient coins")
} catch {
print("unexpected Error")
}
//다음과 같이 모든 에러 상황에 대한 클로저를 작성하여 수행작업을 지정할 수 있다.
//try를 통해 호출하고 에러가 발생 시 catch 클로저로 진행된다.
//catch절은 do 절에서 발생가능한 모든 에러를 처리할 필요는 없다.
func someThrowingFunction() throws -> Int {
//statement
}
let x = try? someThrowingFunction()
do {
y = try someThrowingFunction()
} catch {
y = nil
}
//다음 함수에서 someThrowingFunction()이 에러를 발생시키면, x와 y의 값은 nil이다. 그렇지 않은 경우는 x와 y가 옵셔널 정수값을 가진다.
//try?를 사용하면 모든 에러를 같은 방식으로 처리하려는 경우 간결하게 작성 가능하다.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() {
return data
}
if let data = try? fetchDataFromServer() {
return data
}
return nil // 에러를 다음과 같이 간단하게 처리한다.
}
let photo = try! loadImagE(atPath : "./Resource/John Appleseed.jpg")
//옵셔널 강제 언래핑과 비슷하게 에러도 강제 언래핑 할 경우 런타임 오류가 난다.
func processFile(filename : String) throws {
if exist(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 scope
//여기에서 defer에서 정의한 클로저가 실행된다.
}
}