ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift 오류 처리 - 2
    Programming/Swift(iOS) 2021. 4. 6. 09:51
    728x90

    만약 데이터를 더하다가 오류가 났을때는 이미 추가된 데이터는 어떻게 해야될까요?

     

    1, 이전 데이터로 돌린다. 

    2. 오류 이전까지만 추가한다.

     

    개발자 혹은 기획이 어떻게 되냐에 다르겠지만, 대부분은 1번을 선택 할 것입니다. 

     

    오류 가능성이 있는 연산이 수행되었을 때,

    오류가 발생하게 되면, 오류 발생 이전의 객체 상태로 오류 발생 이후의 상태는 동일해야 한다. => 예외 안정성

     

    아래 코드는 append를 하다가 예외가 발생합니다. 과연 어떤 결과가 나올까요?

    enum LogError:Error {
        case invalidValue
    }
    
    struct Log {
        var values:[String]  = [String]()
        
        mutating func append(messages:[String]) throws {
            for message in messages {
                let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines)
                
                if trimmed.isEmpty {
                    throw LogError.invalidValue
                }
                values.append(message)
            }
        }
    }
    
    var log = Log()
    do {
        try log.append(messages: ["Hello World", "        ", "show me the money"])
    } catch {
        print(error)
    }
    print(log)
    

     

    결과

    invalidValue

    Log(values: ["Hello World"])

     

    오류 나기 전까지만 더 해져있습니다. 

     

    1. 임시 값을 이용하는 방법 , 최종 연산이 된 후에 값이 변경되게 해야됩니다. (복사본 이용)

        mutating func append(messages:[String]) throws {
            var temp = values
            for message in messages {
                let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines)
                
                if trimmed.isEmpty {
                    throw LogError.invalidValue
                }
                temp.append(message)
            }
            values = temp
        }
    

     

    2. defer block을 이용하는 방법

    - 예외가 발생했을 때, 기존 Data를 defer block에서 지워버리는 방법입니다.

    func writeToFiles(data:[URL:String]) throws {
        var completed = [URL]()
        
        //defer block에서는 defer밖으로 Error를 던질 수 없다.
        //try! - 예외가 발생 했을 경우 프로그램 강제 종료
        defer {
            if completed.count != data.count {
                //예외가 발생하면 이전 data를 모두 지우자
                print("예외가 발생했습니다. - \(completed)")
                for url in completed {
                    // 1) try! removeItem을 해보면서 예외가 발생하면 프로그램 강제 종료
                    
                    //try! FileManager.default.removeItem(at: url)
                    
                    // 2) removeItem에 대한 예외처리
                    do {
                        try FileManager.default.removeItem(at: url)
                    } catch {
                        print("복구할 수 없는 오류 발생")
                    }
    
                }
            }
        }
        for (url, contents) in data {
            try contents.write(to: url, atomically: true, encoding: .utf8)
            completed.append(url)
        }
    }
    
    do {
        try writeToFiles(data: [URL(fileURLWithPath: "/Users/hy/Desktop/a.txt"):"hello world"])
        try writeToFiles(data: [URL(fileURLWithPath: "~/b.txt"):"hello world"])
        try writeToFiles(data: [URL(fileURLWithPath: "/Users/hy/Desktop/c.txt"):"hello world"])
    } catch {
        print(error)
    }
    

    3. 불변 객체를 사용하는 방법 

    - 불변 객체를 사용해서 조건 검사후 새로운 객체를 만들면 됩니다.

    enum UserError : Error {
      case invalidAge
    }
    
    struct User {
      let name: String
      let age: Int
    
      func child(childAge: Int) throws -> User {
        if age <= childAge {
          throw UserError.invalidAge
        }
        
        return User(name: "JR.\(name)" , age: childAge)
      }
    }
    
    let user = User(name: "Tom", age: 42)
    print(user)
    do {
      let jr = try user.child(childAge: 50)
      print(jr)
    } catch {
      print(error)
    }
    print(user)
    

    'Programming > Swift(iOS)' 카테고리의 다른 글

    Swift 오류처리 -3  (0) 2021.04.06
    Swift 오류처리 - 3  (0) 2021.04.06
    Swift 오류 처리 - 1  (0) 2021.04.06
    Swift 상속  (0) 2021.04.03
    Swift 초기화 메서드  (0) 2021.04.02
Designed by Tistory.