스위프트 에러, 핸들링,
안일어나면 좋겠지만, 난 에러를 오늘도 만났골랑, 잣같다.
https://jusung.gitbook.io/the-swift-language-guide/language-guide/17-error-handling
Swift에서는 Error 프로토콜을 채택하는 방식으로 표현을 한다.
정확한 타입은 따로 존재하지 않는다.
근데 이 Error 프로토콜 내에는 아무 것도 구현되어 있지 않았다.
애플 문서에서 보면, 스위프트는 간단한 오류는 열거형으로 정의하는 거를 추천한다.
예시를 보면, 매번 강종되는 내 인텔맥북에러를 예로 들어봤다.
에러를 내기 위해서 몇 개의 프로그램을 열어야 하는지와 관련해서 throw구문을 사용할 수 있다고 한다.
throw IntelMacError.openProgram(howMany: 5)
여하튼 이렇게 에러가 나면 이 코드 영역에 에러를 처리해줘야 한다.
스위프트에서는 총 4가지 에러 처리 방법을 제시한다.
(1). 에러를 발생시키는 함수 사용하는 방법 : throws 사용하기
어떤 함수/초기자가 에러를 발생시킬 수 있다는 것을 알리기 위해서 throws를 사용한다.
throws 의 위치를 기억하자! (반환값 앞에 붙는다)
우리는 이거를 throwing function이라고 한다.
throwing function은 함수 내부에서 에러를 던져(throws) 함수가 호출된 곳에 전달한다.
이 말은 문제가 생기는 지점을 밖에 던진다는 것을 의미한다. 그리고 문제가 생기는 요소가 많아서 s를 붙여준 것이다.
예시를 보면,
사용자가 입력한 값이 각각 아래와 같으면 오류를 던질 거라는 뜻이다.
1). 비어있으면 -> ValidationError.emptyString
2). 숫자가 아니면 -> ValidationError.isNotInt
실제로 해당 함수를 불러줬을 때 오류가 던져지고 잡히지 않았다는 콘솔 메시지가 뜬다.
(2). do - try - catch 구문
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch {
statements
}
애플 문서에서 제시되는 do - try - catch문의 기본 형태이다.
catch 구문 뒤에는 각각 어떤 에러인지 적고 각 에러마다 어떻게 처리해줄 것인지 명시할 수 있다.
위에서 사용됐던 그 함수를 다시 가져와서 다시 do - try - catch문으로 살펴보자면,
validateUserInput(text: ) 함수는 try 표현 안에서 호출되는데
<if 에러 발생!!>
만약 에러를 발생시킨다면 그 즉시 catch문 안으로 들어갈 것이다.
여기서 해당 에러를 처리해주는 catch문이 없다면 가장 마지막 catch문에 걸려서 지역 에러 상수인 error로 처리된다.
(각 에러마다 종류 별로 처리해줄 필요는 없지만, 해당 에러를 아무런 처리도 안하면 런타임 에러가 일어날 것이다.)
<else>
아무런 에러도 발생하지 않는다면 do문이 실행된다.
(3). 에러를 optional 값으로 변환하는 방법
try? 구문을 통해서 에러를 옵셔널 값으로 변환할 수 있다.
try? 내에서 발생하면 해당 에러는 nil이 될 것이다.
해당 fetchData()는 만약 데이터를 가져올 때 에러가 발생 시에는 반환값인 data가 nil일 것이다.
(4). try!를 사용해서 강제로 크래쉬를 내는 방법
강제 언래핑을 통해서 이 함수/메소드에서 에러가 발생되지 않을 것을 확신할 경우에 try!를 사용할 수도 있다.
근데 위험을 감수해야 한다는 점...
어느 때에 사용하냐면, 애플 문서의 말을 빌리면,
앱이 배포 시에 이미지가 무조건 포함되어 배포되기 때문에 런타임에 에러가 100퍼센트 나지 않는 것을 확신하는 아래와 같은 상황에서 쓸 수 있다.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
defer
마지막으로 정리 액션 기술 Specifying Cleanup Actions
굉장히 특이하게 번역해뒀다.
defer 구문을 통해 함수가 종료된 후 파일 스트림을 닫거나, 사용했던 자원을 해지하는 등의 일을 할 수 있다.
defer가 여러개 있는 경우 가장 마지막 줄부터 실행된다. = bottom - up 순으로 실행
뭔 말이냐면,, 현재의 코드가 끝나기 전에 꼭 실행되어야 하는 코드들이 실행되는 것을 보장해주는 거다.
그래서 defer 내부에는 break, return 과 같이 해당 코드 블럭을 빠져나가는 코드는 작성하면 안된다.
그래서 defer는 현재 코드의 가장 마지막 실행 블럭이 끝날 때까지 기다렸다가 아래서부터 위로 실행된다.
Swift4.2 이하 버전에서는 do - try - catch / throws 문법을 통해 작업 중에 실패할 수 있는 / 에러가 발생할 수 있는 경우에 대응해줬다. 그러나 이런 에러의 경우는 런타임에 동기로 자동으로 처리할 수 있게 해준 것이라 이외의 발생 가능한 여러가지 예외 상황에 대해 대처하기 어렵다는 단점들이 존재한다.
Swift5에서는 이런 점을 보완해 에러를 보다 유연하게 처리할 수 있는 Result<Value, Error> 문법을 지원한다.
앞서 말한 기존의 Swift가 처리하기 어려웠던 상황 중 하나가 에러의 비동기 처리이다.
해당 에러를 이후 어떻게 보완해 나갔는지는 추후에 살펴보자. 지금은 Error Protocol부터 프로젝트에 적용부터 해보자. 언제할래? 빨리하자..ㅇ...응..
'⭐️ 개발 > iOS & Swift' 카테고리의 다른 글
[iOS] URLSession(1) (0) | 2022.08.30 |
---|---|
[Swift] Codable (2) | 2022.08.29 |
[Swift] WMO - Swift 성능 최적화 (1) | 2022.08.26 |
[Swift] Realm 진짜.그냥.간단.정리 (0) | 2022.08.24 |
[iOS] Realm 기본 설계 + Realm에 저장하고 가져오기 (0) | 2022.08.23 |