에러처리
에러처리 목차
(에러처리의 개념)[#에러처리의-개념]
에러의 종류
에러처리
(에러 처리 방법)[#에러-처리-방법]
try catch (try 문)
(Defer문)[#Defer문]
에러처리의 개념
컴파일 오류
문법적 오류 (에러)
Swift 문법과 관련된 에러이다. (컴파일러가 알려줌)
런타임 오류
앱 실행 중 다양한 이유로 발생 → 앱의 종료
발생 가능한 에러는 미리 처리해야함.
참고: 크래시 (앱의 강제 종료)
에러 처리가 필요한 이유
와이파이 이슈, 서버 이슈 등 다양한 오류가 발생할 수 있음 → 처리를 해 줘야돼!
앱이 무작정 꺼지지 않도록 처리하는 것.
사용자 경험과 관련해서 중요함. (알려주든지, 재시도를 요청하든지)
에러처리
어떤 상황이 발생했을 때, 비정상적인 경우 (에러를 던짐) 를 정의하는 것.
에러 처리의 과정 (3단계)
에러 타입 정의
Error 프로토콜을 채택한 에러 열거형을 정의한다.
Error 프로토콜을 채택하면 정의한 타입 열거형이 Swift의 에러 프로토콜 내로 통합된다.
어떤 에러가 발생할지 미리 정의하는 것이다.
에러가 발생할 수 있는 함수를 정의한다.
각 에러의 종류 (비정상적인 경우)를 분류하여 리턴
throw
키워드로 던짐
에러를 처리한다. (함수의 실행)
try
와do
-catch
문으로 처리한다.do { // 정상적인 경우의 처리 상황 var result = try functionName() // return 값이 있는 경우 } catch { // 위 함수가 에러를 던졌을 때 (에러가 발생한 경우) 처리하는 실행 블럭 }
예제
// 에러의 정의 (열거형)
enum SomeError: **Error** { // **Error 프로토콜** 반드시 채택 필요
case aError
case bError
case cError
}
// 일반 함수
func doSomethine(num: Int) -> Bool {
if num >= 7 {
return true
} else {
return false
}
}
// 에러를 던지는 함수
// 정상적인 경우는 Bool, 비정상적인 경우에는 error를!
func doSomethine(num: Int) **throws** -> Bool {
if num >= 7 {
return true
} else {
if num <0 { // 에러가 나는 조건
**throw SomeError.aError**
}
return false
}
}
try문
정석적인 트라이 try
try
try , do - catch로 사용
모든 에러 발생의 예외적인 경우를 디테일하게 처리 가능
해당 사용에 익숙해져야한다.
do { let data = try parsing() } catch { // 에처처리 }
옵셔널 트라이 try?
try?
옵셔널 타입으로 리턴
정상적인 경우, 리턴 타입으로 리턴
에러 발생 시, nil 리턴
값 사용 시 옵셔널 값을 unwrapping해서 사용해야함.
let data = **try?** parsing()
forced 트라이 try!
try!
에러가 날 수 없는 경우에만 사용
정상적인 경우 리턴 타입으로 리턴
에러가 발생하면 런타임 에러
오류가 없다고 확신할 수 있을 때에만 사용한다. (제한적 사용)
let data = **try!** parsing()
catch 블럭의 구체적인 처리 법
catch 옆에 case를 쓸 수 있다. (에러를 따로 처리하는 경우)
패턴을 모두 정의 (경우를 모두 따로 처리)
do { let isChecked catch HeightError.maxHeight { // 모든 열거형에 대한 처리를 해 주어야 한다. print("") } catch HeightError.minHeight { } catch { // 아무것도 없으면 **defualt 블럭**이 된다. }
// Swift 5.3부터 catch 뒤 케이스를 여러개 나열할 수 있다. do { let isChecked catch case1, case2 { // case 나열 가능 }
패턴 없이 에러를 받아서 처리 (다운캐스팅 후 사용)
catch블럭 내에서 error 상수를 제공한다.
error 상수(error 프로토콜 타입)을 구체적으로 정의한 타입으로 캐스팅하여 switch문 등으로 다시 처리한다.
do { let isChecked catch { // error 상수를 제공 (모든 에러가 넘어옴) print(error) print(error.localizedDescription) // error 프로토콜에 있는 속성, 언어별로 출력해줌 if let error = error as? HeightError { // 다운캐스팅하여 구체적으로 분류할 수 있다. switch error { case .aError: case .bError: } }
Defer문
defer문?
어떤 동작을 마지막으로 미루는 방법이다.
일반적으로 어떤 동작의 마무리 동작을 특정하기 위해 사용한다.
코드의 실행을 스코프가 종료되는 시점으로 연기시키는 문법이다.
예시
func deferStatement1() {
defer {
print("나중에 실행하기")
}
print("먼저 실행하기")
}
func deferStatement2() {
if true {
print("먼저 실행하기")
return
}
defer {
print("나중에 실행하기") // 실행되지 않는다. defer문이 호출되어야, 실행 예약이 된다.
}
}
func deferStatement() {
defer {
print(1)
}
defer {
print(2)
}
defer {
print(3)
}
}
// 3, 2, 1로 실행됨
// 역순으로 출력된다.
// 실 사용에서는 보통 하나만 사용한다.
일반적으로 어떤 동작의 마무리 동작을 특정하기 위해 사용한다. (정리 개념)
defer문을 왜 사용할까?
동작의 마무리를 까먹을 수 잇어서..?
함수에서만 쓸 수있는 것이 아니고, for문에서도 사용할 수 있따.
for i in 1...3 { defer { print ("Defer된 숫자?: \(i)") } // 다음 주기로 넘어가기 전에 실행된다. (총 3번) print ("for문의 숫자: \(i)") } /* for문의 숫자: 1 Defer된 숫자?: 1 for문의 숫자: 2 Defer된 숫자?: 2 for문의 숫자: 3 Defer된 숫자?: 3 */
DEFER
어떤 동작을 마지막으로 미루는 방법
일반적으로 어떤 스코프 내 동작을 마무리하기 위해 사용된다.
defer문은 한 번은 호출되어야지만, 해당 구문이 실행된다.
Last updated