에러 처리(Error Handling)를 다룹니다.
A Swift Tour ( https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html ) 문서의 코드를 Swift Playground( https://swiftfiddle.com/ ) 에서 실행시켜 보며 진행해보았습니다.
본 문서는 공부한 내용을 정리하는 목적으로 작성되었으며 A Swift Tour 문서의 내용을 바탕으로 하고 있습니다. 잘못된 점이 있을 수 있습니다
2021. 11. 06 최초작성
2022. 10. 22 최종수정
Error 프로토콜을 채택하는 모든 타입을 사용하여 에러를 나타낼 수 있습니다. 여기에선 열거형을 사용한 예제를 보여줍니다.
enum PrinterError: Error { case outOfPaper case noToner case onFire } |
throw 키워드를 사용하여 오류를 발생시키고 throws 키워드를 사용하여 해당 함수가 오류를 발생시킬 수있음을 표시합니다.
함수에서 에러가 발생하면 함수가 즉시 반환되고 함수를 호출한 코드가 에러를 처리합니다.
send 함수에서 printerName이 "Never Has Toner"인 경우 열거형에 정의된 PrinterError.noToner 에러를 발생시킵니다.
아니라면 "Job sent"를 리턴합니다.
func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.noToner } return "Job sent" } |
에러를 처리하는 방법에는 여러 가지가 있습니다. 그중 하나는 do-catch를 사용하는 것입니다.
do 블록 내에서 오류를 발생시킬 수 있는 코드 앞에(여기에선 send 함수) try를 추가합니다. catch 문에서 별다른 지정이 없으면 Error 프로토콜을 상속 받은 타입(여기에선 열거형 PrinterError) 에 있는 이름이 출력됩니다.
do { let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng") print(printerResponse) } catch { print(error) } |
같은 코드로 두가지 상황을 보여줍니다. printerName의 값이 "Never Has Toner" 인지 여부에 따라 에러를 발생시킬지 여부가 결정됩니다.
우선 에러가 발생하지 않는 경우입니다. do 문 내에 있는 print 문에서 send 함수의 리턴값 "Job sent"을 출력합니다.
enum PrinterError: Error { case outOfPaper case noToner case onFire } func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.noToner } return "Job sent" } do { let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng") print(printerResponse) } catch { print(error) } |
두번째는 에러가 발생하는 경우입니다. catch문에 있는 print 문에서 에러 메시지 noToner를 출력합니다.
enum PrinterError: Error { case outOfPaper case noToner case onFire } func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.noToner } return "Job sent" } do { let printerResponse = try send(job: 1040, toPrinter: "Never Has Toner") print(printerResponse) } catch { print(error) } |
특정 오류를 처리하는 여러 catch 블록을 제공할 수 있습니다. switch문 내에서 case문을 사용하는 것처럼 할 수 있습니다.
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) } // Prints "Job sent" |
에러를 처리하는 또 다른 방법은 try?를 사용하여 결과를 옵셔널로 변환하는 것입니다.
함수에서 에러가 발생하면 에러는 무시되고 결과는 nil입니다.(두번째 print문)
그렇지 않으면 결과는 함수가 반환한 값을 포함하는 옵셔널입니다.(첫번째 print문)
enum PrinterError: Error { case outOfPaper case noToner case onFire } func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.noToner } return "Job sent" } let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler") print(printerSuccess) let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner") print(printerFailure) |
defer를 사용하면 함수의 모든 코드가 실행된 다음에 마지막으로 실행되는 코드를 지정할 수 있습니다.
함수에 에러를 발생했는지 여부에 관계없이 defer에서 지정한 코드가 실행됩니다.
처음에는 fridgeIsOpen가 true인 상태여서 if문이 실행되어 배열 fridgeContent에 문자열 milk가 있는지 체크합니다.
배열에 문자열 milk가 포함되어 있으므로 result에는 true가 저장되며 함수가 리턴되기 전에 defer에 있는 코드가 실행되어 변수 fridgeIsOpen의 값은 false가 됩니다.
실행결과는 현재 result의 값인 true와 fridgeIsOpen의 값인 false가 출력됩니다.
var fridgeIsOpen = false let fridgeContent = ["milk", "eggs", "leftovers"] func fridgeContains(_ food: String) -> Bool { fridgeIsOpen = true defer { fridgeIsOpen = false } var result = false if fridgeIsOpen == true { result = fridgeContent.contains(food) } return result } var ret=fridgeContains("milk") print(ret) print(fridgeIsOpen) |
실행결과입니다.
Swift 강좌 1 - Hello, world
https://webnautes.tistory.com/1549
Swift 강좌 2 - 상수와 변수
https://webnautes.tistory.com/1550
Swift 강좌 3 - 제어문 : if, for - in, switch, repeat - while
https://webnautes.tistory.com/1551
Swift 강좌 4 - 함수
https://webnautes.tistory.com/1552
Swift 강좌 5 - 객체(Objects)와 클래스(Classes)
https://webnautes.tistory.com/1558
Swift 강좌 6 - 열거형(Enumerations)과 구조체(Structures)
https://webnautes.tistory.com/1559
Swift 강좌 7 - 프로토콜(Protocols)과 익스텐션(Extensions)
https://webnautes.tistory.com/1562
Swift 강좌 8 - 에러 처리(Error Handling)
https://webnautes.tistory.com/1566
Swift 강좌 9 - 제네릭(Generics)
https://webnautes.tistory.com/1568
'Swift' 카테고리의 다른 글
Swift 강좌 9 - 제네릭(Generics) (0) | 2022.10.22 |
---|---|
Swift 강좌 7 - 프로토콜(Protocols)과 익스텐션(Extensions) (0) | 2022.10.22 |
Swift 강좌 6 - 열거형(Enumerations)과 구조체(Structures) (0) | 2022.10.22 |
Swift 강좌 5 - 객체(Objects)와 클래스(Classes) (0) | 2022.10.22 |
Swift 강좌 4 - 함수 (0) | 2022.10.22 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!