에러 핸들링
- 활성화된 인터넷 연결을 기반으로 동작하는 앱은 디바이스가 네트워크 신호를 잃는 것을 제어할 수 없음
- 에러 처리를 해야 함
- ex) 앱을 계속 사용하려면 인터넷 연결이 필요하다는 메시지 띄우기
- 에러 처리 2단계
- iOS 앱의 메서드 내에서 원하는 결과가 나오지 않을 경우 에러 발생 (스로잉)
- 메서드가 던진 에러를 잡아서 처리
- 에러를 던진 경우, 해당 에러는 에러의 특성을 식별하여 적절한 동작을 결정하는 데 사용되는 특정 에러 타입 중 하나가 됨
- 에러 타입 값은 Error 프로토콜을 따르는 모든 값이 될 수 있음
에러 타입 선언
- 원격 서버 파일을 전송하는 메서드가 있다고 하자.
- 이 메서드는 여러 원인(네트워크 연결 x, 네트워크 속도 느림, 전송할 파일 찾지 못함)으로 인해 파일 전송에 실패 가능성 있음
- → 이러한 에러는 다음과 같이 Error 프로토콜을 따르는 열거형 내에서 표현되도록 함
// 에러 타입 선언
enum FileTransferError : Error {
case noConnection
case lowBandwith
case fileNotFound
}
→ 에러 타입 선언했으니 에러가 발생했을 때 사용 가능
에러 던지기
- 메서드나 함수가 에러를 던질 수 있다는 것을 선언 할 때는 다음과 같이 throws 키워드 사용
// 에러 던지기
func transferFile() throws {
}
// 결과를 반환하는 메서드나 함수의 경우, throws 키워드는 반환 타입 앞에 위치 해야 함
func transferFile() throws -> Bool {
}
- 오류가 발생할 때 에러를 던지는 코드 추가
- 상태 값으로 제공되는 상수들을 선언 후, 메서드에 대한 guard 동작과 throw 동작 구현
let connectionOK = true
let connectionSpeed = 30.0
let fileFound = false
enum FileTransferError : Error {
case noConnection
case lowBandwith
case fileNotFound
}
func fileTransfer() throws {
guard connectionOK else {
throw FileTransferError.noConnection
}
guard connectionSpeed > 30 else {
throw FileTransferError.lowBandwith
}
guard fileFound else {
throw FileTransferError.fileNotFound
}
}
→ throw 구문과 guard 구문 결합하여 사용
- guard 구문은 각 조건이 참인지 아닌지 검사
- 거짓이라면 else 구문에 포함된 코드 실행
에러를 던지는 메서드와 함수 호출
- 메서드 또는 함수가 에러를 던지도록 선언했다면 일반적인 방법으로는 호출 불가능
- 이러한 메서드를 호출할 때는 try 구문을 붙여야 함
try fileTransfer()
- try 구문을 이용하는 방법 외에도 던져진 모든 에러를 잡아서 처리하는 do-catch 구문 내에서 호출하는 방법
- ex) fileTransfer() 메서드를 sendFile() 이라는 메서드 내에서 호출한다고 가정
func sendFile() -> String { do { try fileTransfer() } catch FileTransferError.noConnection { return "No Network Connection" } catch FileTransferError.lowBandwith { return "File Trnasfer Speed too Low" } catch FileTransferError.fileNotFound { return "File Not Found" } catch { return "UnKnown Error" } return "Successul transfer" }
- 에러 없이 성공하면 "Successul transfer" 리턴
- 에러에 대한 패턴 매칭이 이뤄지지 않은 상태 "UnKnown Error" 리턴
- → catch all 구문으로 앞선 catch 구문과 일치하지 않은 모든 에러를 처리 가능 ('catch { return "UnKnown Error" } ')
- do-catch 구문은 가능한 모든 에러에 대해 처리할 수 있도록 구성되어야 하기 때문
에러 객체 접근
- 메서드 호출이 실패하면 반드시 실패한 원인을 구별할 수 있는 MSError 객체가 반환됨
- catch 구문에서 가장 필요한 것은 이 객체에 접근하여 적절한 동작을 실시하는 것
- 새로운 파일 시스템 디렉터리를 생성하고자 할 때 catch 구문 내에서 여러 객체에 접근하는 방법을 보여줌
do {
try filemgr.createDirectory(atPath: newDir, withIntermediateDirectories : true attributes: nil)
} catch let error {
print("Error : \(error.localizedDesciption)")
}
에러 캐칭 비활성화
- try! 구문 사용 → do-catch 구문 내에서 메서드가 호출되도록 감싸지 않아도 스로잉 메서드가 강제 실행
try! fileTransfer
→ 컴파일러에게 이 메서드 호출은 어떠한 에러도 발생하지 않을 것이라고 알려주는 것과 동일
에러가 발생한다면 런타임 에러 → 가급적 사용 x
defer 구문 사용하기
- sendFile 메서드는 에러 처리하는 일반적인 시나리오
- do-catch 구문에 있는 각각의 catch 절은 호출하는 메서드에게 제어권을 반환하기 위해 return 사용
- 하지만, 에러의 종류와 상관없이 제어권을 반환하기 전에 어떤 별도 작업을 수행하는 게 효과적일 수 있음
- ex) sendFile 메서드에서 제어권 반환 전 임시 파일을 지워할 경우 → defer 구문 사용
- defer 구문은 메서드가 결과 반환하기 직전 수행되어야 하는 일련의 코드 지정
func sendFile() -> String {
defer {
removeTmpFiles()
closeConnection()
}
do {
try fileTransfer()
} catch FileTransferError.noConnection {
return "No Network Connection"
} catch FileTransferError.lowBandwith {
return "File Trnasfer Speed too Low"
} catch FileTransferError.fileNotFound {
return "File Not Found"
} catch {
return "UnKnown Error"
}
return "Succeccsul transfer"
}
→ 제어권 반환 전 removeTmpFiles, closeConnection 메서드 호출 됨
'Swift' 카테고리의 다른 글
Swift - 구조체 정의 (Decodable) - Codingkey 사용 (0) | 2024.08.10 |
---|---|
Swift - Xcode 프로젝트 생성 (0) | 2024.06.24 |
Swift - 9. 배열과 딕셔너리 (1) | 2024.01.06 |
Swift - 8. 프로퍼티 래퍼 (0) | 2023.12.29 |
Swift - 7. 구조체 (0) | 2023.12.28 |