Codable, NSCoding

Lena·2021년 3월 14일
0

모델 객체의 인스턴스를 데이터 타입으로 인코딩하거나, 데이터를 모델 객체 타입으로 디코딩할 때 Codable과 NSCoding 프로토콜을 사용할 수 있다.

Codable

Codable
typealias Codable = Encodable & Decodable

  • Encodable -- 객체를 원하는 데이터 형태로 변환(encoding)
  • Decodable -- 데이터를 모델 객체로 변환(decoding)

class, struct, enum에 모두 Codable protocol을 채택할 수 있다.

CodingKey Protocol

CodingKey 프로토콜을 채택해서 json 데이터의 key와, 속성의 이름과 다르게 지정할 수 있다.

Decodable

decoder를 이용해서 init()을 구현할 수 있다. (JSON으로부터 데이터 빼내기)

extension User: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        birth = try container.decode(String.self, forKey: .birth)
        phoneNum = try container.decode(String.self, forKey: .phoneNum)
    }
}

Encodable

decode와 반대로 encode 함수를 작성한다.

// encode 함수 직접 구현
func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: Codingkeys.self)
    try contrainer.encode(someDate, forKey: .someDate)
}

Codable은 속성의 타입이 지정되어 있는(Int, String...) 경우에만 사용할 수 있다.
struct 안의 struct를 갖고 있거나, Any 타입을 속성으로 갖고 있는 타입은 Codable을 채택할 수 없다.

Read Data from Arrays

배열 형태로부터 Data를 얻는 예제는 다음과 같다.

let json = """
[
    {
        "name": "Banana",
        "points": 200,
        "description": "A banana grown in Ecuador."
    },
    {
        "name": "Orange",
        "points": 100
    }
]
""".data(using: .utf8)!

struct GroceryProduct: Codable {
    var name: String
    var points: Int
    var description: String?
}

let decoder = JSONDecoder()
let products = try decoder.decode([GroceryProduct].self, from: json)

See Also

NSCoding

다이나믹하게 다형성으로 동작하는 방식이 필요한 경우에는 NSCoding 프로토콜을 사용하는 것이 권장된다.
(Codable과 동시에 채택도 가능하다)

class NBeverage : NSObject, NSCoding {
    private var brand : String = ""
    required init?(coder: NSCoder) {
        self.brand = coder.decodeObject(forKey: "brand") as! String
    }
    
    func encode(with coder: NSCoder) {
        coder.encode(brand, forKey: "brand")
    }
}

required initencode 메서드 구현이 필요하다.

NSKeyedArchiver

NSCoding 프로토콜을 채택한 객체는 NSKeyedArchiver로 인코딩, NSKeyedUnarchiver로 디코딩한다.
아카이브 한 결과는 Data 타입이 되고, json 형식은 불가능하다.
(json 형식으로 데이터를 전송하려면 UserDefault or Plist 파일을 이용해서 저장하는 방법이 있다)

static func unarchive(with text: Data) -> Any? {
        do {
            let object = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(text)
            return object
        }
        catch {
            print(error)
        }
        return nil
    }
    
    static func archive<T>(with things: T) -> Data {
        do {
            let archived = try NSKeyedArchiver.archivedData(withRootObject: things, requiringSecureCoding: false)
            return archived
        }
        catch {
            print(error)
        }
        return Data()
    }

Codable과 NSCoding의 차이는 다음 블로그 글을 참고😉


https://shark-sea.kr/entry/Swift-Codable-알아보기

0개의 댓글