Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
47
Help us understand the problem. What is going on with this article?
@hanawat

Swift4.0 で追加される Codable

More than 3 years have passed since last update.

※ まだ正式リリースされていない情報なので変更の可能性があります🙇

Swift3まではstructenumをデータとして保存や読み込みをする際に必要となるオブジェクトのシリアライズとデシリアライズのために一発NSCodingプロトコルに準拠したNSObjectを噛ませなければいけませんでした😭

struct Person {

  let name: String
  let age: Int
}

extension Person {

  class Helper: NSObject, NSCoding {

    let person: Person?

    init(person: Person) {
      self.person = person
      super.init()
    }

    required init?(coder aDecoder: NSCoder) {
      guard
        let name = aDecoder.decodeObject(forKey: "name") as? String,
        let age = aDecoder.decodeObject(forKey: "age") as? Int else {
          return nil
      }

      person = Person(name: name, age: age)
      super.init()
    }

    func encode(with aCoder: NSCoder) {
      guard let person = person else { return }

      aCoder.encode(person.name, forKey: "name")
      aCoder.encode(person.age, forKey: "age")
    }
  }
}

let person = Person(name: "Foo", age: 10)
let helper = Person.Helper(person: person)
let data = NSKeyedArchiver.archivedData(withRootObject: helper)

ただ、PersonをDataにしたいだけなのにこの手間。Swift4ではCodableというプロトコルがFoundationに追加されて解決しました☺️


struct Person: Codable {

  enum Child: String, Codable {
    case son, daughter
  }

  let name: String
  let age: Int
  let children: [Child]
}

let person = Person(name: "Foo", age: 10, children: [.son, .daughter])
let data = try? JSONEncoder().encode(person)

これだけで済むのです👏エンコードを例にしましたが、定義元を見るとわかるのですがデコードも可能です。しかもSwift4で追加されたプロトコルの&が使われている👏

/// A type that can convert itself into and out of an external representation.
public typealias Codable = Decodable & Encodable

これならAPIなどで取得したデータをパースする時の処理に外部ライブラリを使わなくても済みますね。

let person = try? JSONDecoder().decode(Person.self, from: data)

このEncoderは現在JSONEncoderPropertyListEncoderのみですが、今後増えて行くと思います。

しかもこの検証をPlaygroundで行なっていたところ、バイナリデータのサイズに大きな違いがあることも分かりました🎉前者がデカいのはNSObjectを継承しているためでしょう。

let data = NSKeyedArchiver.archivedData(withRootObject: helper) // 299 bytes
let data = try? JSONEncoder().encode(person)                    // 53 bytes

おしまい👏

47
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
hanawat
iOS Engineer

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
47
Help us understand the problem. What is going on with this article?