Error 프로토콜을 채택하는 모든 타입을 사용하여 에러를 나타낸다.
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
에러를 던지기 위해 throw를 사용하고 에러를 던질 수 있는 함수를 나타내기 위해 throws를 사용한다.
함수에서 에러가 발생하면 함수는 즉시 반환되고 함수를 호출한 코드가 에러를 처리한다.
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
에러를 처리하는 방법이 몇 가지 존재한다.
한 가지 방법은 do-catch를 사용하는 것이다.
do 블럭 내에서 앞에 try를 작성하여 에러가 발생할 수 있는 코드임을 표시합니다.
catch 블럭 내에서 에러는 다른 이름으로 지정하기 전까지는 자동으로 error라는 이름으로 주어진다.
do {
let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
print(printerResponse)
} catch {
print(error)
}
특정 에러를 처리하는 여러개의 catch 블럭을 제공할 수 있다.
스위치에서 case 이후에 하는 것처럼 catch 이후에 패턴을 작성한다.
do {
let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
print(printerResponse)
} catch PrinterError.onFire {
print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
print("Printer error: \(printerError).")
} catch {
print(error)
}
에러를 처리하는 다른 방법은 결과를 옵셔널로 바꾸는 try?를 사용하는 것이다.
함수에서 에러가 발생하면 특정 에러는 버려지고 결과는 nil로 처리되며,
그렇지 않으면 결과는 함수가 반환한 옵셔널 값을 가진다..
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
함수를 반환하기 직전에 함수의 다른 모든 코드 다음에 실행되는 코드 블럭을 작성하기 위해 defer를 사용한다.
이 코드는 함수에서 에러가 발생하는지 여부와 관계없이 실행된다.
서로 다른 시간에 실행되어야 하는 경우에도 설정 및 정리 코드를 나란히 작성하기 위해 defer를 사용할 수 있다.
var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]
func fridgeContains(_ food: String) -> Bool {
fridgeIsOpen = true
defer {
fridgeIsOpen = false
}
let result = fridgeContent.contains(food)
return result
}
if fridgeContains("banana") {
print("Found a banana")
}
print(fridgeIsOpen)
// Prints "false"