Swift의 에러 핸들링 이해하기

2 분 소요

에러 핸들링 이해하기

에러 처리 단계

  1. iOS 앱의 메서드 내에서 원하는 결과가 나오지 않을 경우 에러 발생( 스로잉(throwing) )
  2. 메서드가 던진(throwing) 에러를 잡아서 처리

에러 타입 값

  • Error 프로토콜을 따르는 모든 값
  • 에러의 특성을 식별하여 취할 수 있는 가장 적절한 동작을 결정

에러 타입 선언하기

enum FileTransferError: Error {
    case noConnection // 네트워크 연결x
    case lowBandwidth // 네트워크 속도 느림
    case fileNotFound // 전송할 파일을 찾지 못함
}

Error 프로토콜을 따르는 열거형 내에서 표현


에러 던지기

  • 메서드나 함수가 에러를 던질 수 있다는 것을 선언할 때: throws 키워드
    func transferFile() throws {
    }
    

    결과를 반환하는 메서드나 함수의 경우

    func transferFile() throws -> Bool {
    }
    
  • 오류가 발생할 때 에러를 던지는 코드: throw 구문과 guard 구문
    let connectionOK = true
    let connectionSpeed = 30.00
    let fileFound = false
    
    enum FileTransferError: Error {
        case noConnection
        case lowBandwidth
        case fileNotFound
    }
    
    func fileTransfer() throws {
    
        guard connectionOK else {
            throw FileTransferError.noConnection
        }
    
        guard connectionSpeed > 30 else {
            throw FileTransferError.lowBandwidth
        }
    
        guard fileFound else {
            throw FileTransferError.fileNotFound
        }
    }
    

에러를 던지는 메서드와 함수 호출하기

에러를 던지는 메서드 호출 시: try 구문

try fileTransfer()

And
do-catch 구문: 던져진 모든 에러를 잡아서 처리
try 구문은 반드시 do-catch 구문으로 감싸여야 함

func sendFile() -> String {

    do {
        try fileTransfer()
    } catch FileTransferError.noConnection {
        return "No Network Connection"
    } catch FileTransferError.lowBandwidth {
        return "File Transfer Speed too Low"
    } catch FileTransferError.fileNotFound {
        return "File not Found"
    } catch { // (catch all 구문 - 반드시 필요)
        return "Unknown error" // 에러에 대한 패턴 매칭x
    }

    return "Successful transfer" // 에러x
}

connectionSpeed 변수가 guard 구문에 막혀 에러를 던짐
-> “File Transfer Speed too Low” 반환


에러 객체에 접근하기

메서드 호출 실패시 NSError 객체가 반환
이 객체에 접근하여 앱 코드 내에서 취할 수 있는 가장 적절한 동작을 실시

do {
    try fileTransfer()
} catch let error {
    print("Error: \(error.localizedDescription)")
}

localizedDescription: A string containing the localized description of the error.


에러 캐칭 비활성화하기

do-catch 구문 내에서 메서드가 호출되도록 감싸지 않아도 스로잉 메서드 강제 실행

try! fileTransfer

어떠한 에러도 발생하지 않을 것이란 확신이 있을 때 사용
에러 발생시 런타임 에러 - 가급적 사용x


defer 구문 사용하기

에러의 종류와는 상관없이 제어권을 반환하기 전에 어떠한 별도의 작업을 수행: defer 구문

func sendFile() -> String {

    defer {
        removeTmpFiles()
        closeConnection()
    }

    do {
        try transferFile()
    } catch FileTransferError.noConnection {
        return "No Network Connection"
    } catch FileTransferError.lowBandwidth {
        return "File Transfer Speed too Low"
    } catch FileTransferError.fileNotFound {
        return "File not Found"
    } catch {
        return "Unknown error"
    }

    return "Successful transfer"
}

어떠한 반환을 하든지 제어권을 반환하기 전에
removeTmpFiles 메서드와 closeConnection 메서드가 항상 호출