Swift | Error, Error Handling

여러분은 에러핸들링을 어떻게 실행하고 있습니까? (번역톤)

가장 잘 활용되는 곳은 API 통신에서 무언가에 실패했을 때
에러 메세지를 유저에게 띄우거나 다른 화면을 띄우는 것이겠지요.

iOS 개발, Swift를 사용할 때 Error Handling은 어떻게 되는지 알아보러 가보실까요 ~ ?
고고싱 ~~~~ ! 🚑🚓



Error

🔗 https://developer.apple.com/documentation/swift/error

Swift 에서 Error는 protocol 입니다.
정확한 type로 제시되어 있지 않은 상태이죠.

struct StructTypeError: Error {}
class ClassTypeError: Error {}
enum EnumTypeError: Error {}

✔️ Error procotol을 상속하기만 하면 strcut, class, enum 모두 다 만들 수 있습니다.


Swift’s enumerations are well suited to represent simple errors. Create an enumeration that conforms to the Error protocol with a case for each possible error. If there are additional details about the error that could be helpful for recovery, use associated values to include that information.

Apple의 문서를 살펴보면, Swift에서 간단한 오류는 enum으로 정의하는 것을 추천하고 있습니다.

네트워크 통신의 400번대의 Error처럼 어느정도 케이스가 정해져 있으니,
Error를 enum으로 정의하고 케이스를 나눠둔다면 실제 코드에서는 케이스별 핸들링을 하는게 좋겠지요 🤟💫

enum DownlaodError: Error {
    case network
    case battery
    case storage

    var errorMessage: String {
        switch self {
        case .network:
            return "네트워크 연결을 확인해주십시오."
        case .battery:
        return "배터리 충전이 필요합니다."
        case .storage:
        return "저장공간이 부족합니다."
        }
    }
}

저는 무언가를 서버에서 다운로드할 때 발생할 수 있는 Error를
3가지 케이스로 나눠 enum으로 정의해보았어요.


자, enum으로 정의한 Error가 실제 코드에서 나타나면 어떻게 핸들링해야하는지 알아보러 가시죠 ~ 🚑🚓


throws

func download() throws {
    guard networkExist else { throw DownlaodError.network }

    accessToken()
    ...
}

throw 는 의미 그대로 발생한 Error 를 던지고 그대로 함수를 종료시킵니다.

try, do-catch

func didTapDownloadButton() {
    do {
        try download()
    } catch DownlaodError.network {
        print(DownlaodError.network.errorMessage)
    } catch DownlaodError.battery {
           print(DownlaodError.battery.errorMessage)
    } catch DownlaodError.storage {
           print(DownlaodError.storage.errorMessage)
    } catch {
        print("알 수 없는 에러가 발생하였습니다.")
    }

    print("다운로드가 완료되었습니다.")
}

✔️ trythrows 가 함께 선언된 메소드를 실행시킬 때 사용합니다.
✔️do-catchthrows 로 선언된 메소드에서 에러를 잡아서 처리할 때 사용합니다.

func didTapDownloadButton() {
    try! download()

    print("다운로드가 완료되었습니다.")
}

try!
– throws 가 함께 선언된 메소드이지만, 절대 error가 발생하지 않는다는 전제에서 사용됩니다.
– Optional에서의 !와 같이 완전한 확신이 있지 않은 이상에는 사용하지 않는걸 추천드려요 🤢

func didTapDownloadButton() {
    do {
        try download()
    } catch let error {
        if let downloadError = error as? DownlaodError {
            print(downloadError.errorMessage)
        }
    }

    print("다운로드가 완료되었습니다.")
}

catch let
try 에서 던져지는 error를 property로 정의하여 사용할 수 있게 합니다.


defer

1. 사용자가 다운로드 버튼을 터치.
2. 서버와 네트워킹
3. 다운로드 성공 or 다운로드 실패(= 에러 발생)
4. 사용자에게 다운로드 성공 또는 실패 결과 알리기

4는 3까지의 모든 실행이 끝난 후 실행되어야 합니다.
3까지의 실행이 확실히 끝이 때 활용할 수 있는 것이 바로 defer 입니다.

✔️ deferdefer문 이후의 실행이 완 ~ 전히 끝난 뒤 ! 실행됩니다.

let networkExist = false
let enoughBattery = false
let enoughStorage = false

func didTapDownloadButtons() {
    defer {
        print("다운로드가 완료되었습니다.")
    }

    do {
        try download()
    } catch DownlaodError.network {
        print(DownlaodError.network.errorMessage)
    } catch DownlaodError.battery {
           print(DownlaodError.battery.errorMessage)
    } catch DownlaodError.storage {
           print(DownlaodError.storage.errorMessage)
    } catch {
        print("알 수 없는 에러가 발생하였습니다.")
    }
}

didTapDownloadButtons()

// 💫💫 결과 💫💫
// 네트워크 연결을 확인해주십시오.
// 다운로드가 완료되었습니다.




Error 타입이 다양한 경우 do, catch, defer 로 100% 커버하지 못할 때도 있어요 🤧
그럴땐 PromiseKit을 활용하시면 간단한 코드로 다양한 타입에 대처할 수 있답니다.
나중에 PromiseKit 의 사용에 대해서도 간단히 한 번 써볼게요 ~

오늘도 즐거운 iOS 개발되세용 🚓🚑🚓🚑

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중