22. Error Handling

26461 단어 swiftswift

코드에서 발생할 수 있는 다양한 오류를 크래시 없이 처리하는 방법에 대해 공부

Error Handling

Swift의 에러 처리 패턴에 대해 공부

Error Handling

throw expression

func name(parameters) throws -> ReturrnType {
	statements
}
init(parameters) throws {
	statements
}
{ (parameters) throws -> ReturnType in
	statements
}

에러를 전달한다 -> 에러를 던진다

enum DataParsingError: Error {
    case invalidType
    case invalidField
    case missingRequiredField(String)
}

func parsing(data: [String: Any]) throws {
    guard let _ = data["name"] else {
        throw DataParsingError.missingRequiredField("name")
    }
    guard let _ = data["age"] as? Int else {
        throw DataParsingError.invalidType      // throw 키워드를 쓴다고 해서 다 호출 되는것은 아님
        // 에러를 발생 된 경우에만 호출 됨
    }
    // Parsing
}

try Statements

try expression
try? expression
try! expression
// throw를 호출하려면 try 키워드 호출해야한다.

try? parsing(data: [:]) // 옵셔널 try? 로 호출할 경우 크레쉬가 나지 않는다
// nil을 리턴하고 호출문 종료

// 에러를 처리하는 방법 3가지
// 1. do-catch를 사용 (코드에서 발생한 오류를 개별적으로 잡을 때 사용)
// 2. try Expression + Optional Binding 함께 사용
// 3. hand over (전달받은 에러를 다른 코드 블럭에 다시 전달)

do-catch Statements

do-catch문을 통해 오류를 처리하는 방법에 대해 공부

do {
	try expression
    statements
} catch pattern {
	statements
} catch pattern where condition {
	statements
}
enum DataParsingError: Error {
   case invalidType
   case invalidField
   case missingRequiredField(String)
}

func parsing(data: [String: Any]) throws {
   guard let _ = data["name"] else {
      throw DataParsingError.missingRequiredField("name")
   }
   
   guard let _ = data["age"] as? Int else {
      throw DataParsingError.invalidType
   }
   
   // Parsing
}
func handleError() throws {
    do {
        try parsing(data: ["name": ""])
    } catch {
        if let erroer = error as? DataParsingError {
            switch error {
            case .invalidType:
                print("invalid type")
            default:
                print("handle error")
            }
        }
    }
}

Multi-pattern Catch Clauses

하나의 catch 블록에서 두 개 이상의 에러를 매칭시키는 문법을 공부

enum DataParsingError: Error {
   case invalidType
   case invalidField
   case missingRequiredField(String)
}

func parsing(data: [String: Any]) throws {
   guard let _ = data["name"] else {
      throw DataParsingError.missingRequiredField("name")
   }
   
   guard let _ = data["age"] as? Int else {
      throw DataParsingError.invalidType
   }
   
   // Parsing
}

do {
   try parsing(data: [:])
} catch DataParsingError.invalidType, DataParsingError.invalidField {       // ,하나로 에러를 매칭시킴
   
} catch DataParsingError.missingRequiredField(let fieldName) {
   
} catch {
   
}


do {
   try parsing(data: [:])
} catch DataParsingError.missingRequiredField(let fieldName) {
   
} catch {
   
}

Optional Try

전달된 오류를 옵셔널 값으로 처리하는 방법에 대해 공부

try? expression
Optional try
---------------
try! expression
Forced try
enum DataParsingError: Error {
   case invalidType
   case invalidField
   case missingRequiredField(String)
}

func parsing(data: [String: Any]) throws {
   guard let _ = data["name"] else {
      throw DataParsingError.missingRequiredField("name")
   }
   
   guard let _ = data["age"] as? Int else {
      throw DataParsingError.invalidType
   }
   
   // Parsing
}

if let _ = try? parsing(data: [:]) {
    print("success")
} else {
    print("fail")
}


do {
    try parsing(data: [:])
    print("success")
} catch {
    print("fail")
}

// 함수만 호출하고 결과를 신경을 필요가 없다면 아래와 같이 하면 됨
try? parsing(data: [:])

try! parsing(data: ["name" : "steve", "age" : "22"])

defer Statements

Scope 종료 시점으로 코드의 실행을 연기하는 방법에 대해 공부

defer {
	statements
}
// defer = 실행 순서를 뒤로 미룸
func processFile(path: String) {
    print("1")
    let file = FileHandle(forReadingAtPath: path)
    
    // Process
    
    defer {
        print("2")
        file?.closeFile()
    }
    
    
    if path.hasSuffix(".jpg") {
        print("4")
        return
    }
    
    defer {
        print("5")
    }
    
    print("4")
    
}

//processFile(path: "file.Swift")

func testDefer() {
    defer {
        print(1)
    }
    defer {
        print(2)
    }
    defer {
        print(3)
    }
}

testDefer()

// 하나의 defer문만 사용하는게 좋음. 

좋은 웹페이지 즐겨찾기