이 포스팅은 iOS BoostCourse 시리즈 23 편 중 17 번째 글 입니다.

  • Part 1 - 01: Asset, App thinning
  • Part 2 - 02: Foundation, UIKit
  • Part 3 - 03: Auto Layout
  • Part 4 - 04: View 체계
  • Part 5 - 05: 디자인 패턴
  • Part 6 - 06: MVC
  • Part 7 - 07: Apple Development Documents
  • Part 8 - 08: Human Interface Guidelines
  • Part 9 - 09: 화면 전환
  • Part 10 - 10: 뷰의 상태 변화 감지
  • Part 11 - 11: Delegation
  • Part 12 - 12: Singleton
  • Part 13 - 13: Target-Action
  • Part 14 - 14: Gesture Recognizer
  • Part 15 - 15: TableView
  • Part 16 - 16: Segue
  • Part 17 - This Post
  • Part 18 - 18: PhotoKit
  • Part 19 - 19: 동시성, 비동기, 병렬 프로그래밍
  • Part 20 - 20: OperationQueue
  • Part 21 - 21: SchrollView
  • Part 22 - 22: Naviagtion item, Bar button item
  • Part 23 - 23: CollectionView
▼ 목록 보기

Codable

typealias Codable = Decodable & Encodable
  • 스위프트 4에서 제공된 기능
  • 인스턴스를 다른 데이터 형태로 변환
  • 그 반대도 가능
  • 스위프트 인스턴스를 다른 데이터 형태로 변환하는 것을 Encodable
  • 그 반대를 Decodable
  • 이 두개를 합한 타입을 Codable로 정의
  • 이런 Codable은 서버 통신에서 유용하게 사용
  • 만약 Json 형식으로 서버와 애플리케이션이 통신한다면 Codable을 사용할 수 있음

image

struct Coordinate: Codable {
    var latitude: Double
    var longitude: Double
}

struct Landmark: Codable {
    var name: String
    var foundingYear: Int
    var vantagePoints: [Coordinate]
    var metadate: [String:String]
    var website: URL?
}
  • Coordinate, Landmark 타입의 인스턴스를 다른 데이터 형식으로 변환하고 싶다.
  • 이런 경우 Codable 프로토콜을 준수하도록 선언하면 알아서 해준다.
  • 스위프트의 기본 타입은 대부분 Codable 프로토콜을 준수한다.

CodingKey

  • 그런데, 기본적으로 구조체의 프로퍼티의 이름이 Json의 Key로 들어가게 된다.
  • 이렇게 되길 원하지 않는 경우도 있다.
  • 이럴 경우 CodingKeys 라는 이름의 열거형을 선언하고, CodingKey 프로토콜을 준수하도록 하면 해결
struct Landmark: Codable {
    var name: String
    var foundingYear: Int
    var vantagePoints: [Coordinate]
    
    enum CodingKeys: String, CodingKey {
        case name = "title"
        case foundingYear = "founding_date"
        case location
        case vantagePoints
    }
}

JSONEncoder / JSONDecoder

  • Swift4 버전 이전에는 JSONSerialization을 사용하여 JSON 타입 데이터 생성
  • 이제는 Codable 프로토콜 사용

JSONEncoder

instacne -> JSON

import Foundation

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

let pear = GroceryProduct(name: "Pear", points: 250, description: "A ripe pear.")

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

do {
    let data = try encoder.encode(pear)
    print(String(data: data, encoding: .utf8)!)
} catch {
    print(error)
}

/* Prints:
 {
   "name" : "Pear",
   "points" : 250,
   "description" : "A ripe pear."
 }
*/

JSONDecoder

import Foundation

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

let json = """
    {
        "name": "Durian",
        "points": 600,
        "description": "A fruit with a distinctive scent."
    }
    """.data(using: String.Encoding.utf8)!

let decoder = JSONDecoder()

do {
    let product = try decoder.decode(GroceryProduct.self, from: json)
    print(product.name)
} catch {
    print(error)
}

Reference