Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Codableのinit(from:)をどう書くか / 20170621 #wwdc_ebisu

Codableのinit(from:)をどう書くか / 20170621 #wwdc_ebisu

WWDC After Party 2017 @Ebisu - connpass
https://pre-wwdc.connpass.com/event/56731/
での発表資料です。

# 参考資料

What's New in Foundation - WWDC 2017 - Videos - Apple Developer
https://developer.apple.com/videos/play/wwdc2017/212/

Search · Codable repo:apple/swift path:stdlib
https://github.com/search?l=Swift&q=Codable+repo%3Aapple%2Fswift+path%3Astdlib&ref=advsearch&type=Code&utf8=%E2%9C%93

704056da9a4c4e075ad14479beaebab7?s=128

takasek

June 21, 2017
Tweet

Transcript

  1. Codableͷinit(from:)Λ Ͳ͏ॻ͔͘ by. 2017/6/21 WWDC After Party 2017 @Ebisu 1

  2. takasek iOS Developer ϑϦʔϥϯε(΄΅FiNC) @takasek OSS ActionClosurable Notifwift౳ 2

  3. QiitaͰCodableؔ࿈ͷهࣄ ࿈౤ͯ͠·͢ 3

  4. - લஔ͖ - Codable ஌ͬͯ·͔͢ʁ 4

  5. Codable introduced in WWDC2017 https://developer.apple.com/videos/play/wwdc2017/212/ 5

  6. Codable͸ϞςϞς ֤ॴWWDCৼΓฦΓձͰ౓ʑϐοΫΞοϓத 6/14 AKIBA.swift / by fromkkɹ6/15 eureka Meetup /

    by Muukiiɹ6/19 CA.swift / by inamiy !ͬ͘͟Γ֓ཁ௫ΊΔࢿྉɹɹ!DecodingErrorʹ͍ͭͯৄ͍͠ɹɹ!I/FɺίϯύΠϥڍಈʹ͍ͭͯ 6
  7. 7

  8. 8

  9. 9

  10. - ຊ୊ -ɹ init(from:) ΛͲ͏ॻ͔͘ 10

  11. Codable Philosophy 4 Error handling built-in 4 ૊Έࠐ·ΕͨΤϥʔ੍ޚ 4 Encapsulate

    encoding details 4 ΤϯίʔσΟϯάͷৄࡉΛΧϓηϧԽ 4 Abstract format from type 4 ந৅Խ͞ΕͨϑΥʔϚοτ 11
  12. Codable Philosophy 4 Error handling built-in 4 ૊Έࠐ·ΕͨΤϥʔ੍ޚ 4 Encapsulate

    encoding details 4 ΤϯίʔσΟϯάͷৄࡉΛΧϓηϧԽ 4 Abstract format from type 4 ந৅Խ͞ΕͨϑΥʔϚοτ 12
  13. CodableɺCoderɺContainer 13

  14. 4 (En|De)codable 4 CoderͱContainerΛ࢖͏͕ɺ ͦͷৄࡉ͸஌Βͳ͍ϐϡΞͳܕ 4 (En|De)coder 4 ࣗ෼ͷ۩ମܕʹ͍ͭͯCodable ʹ͸஌Βͤͳ͍

    4 Codableͷ఩ֶʮந৅Խ͞Εͨ ϑΥʔϚοτʯͷମݱऀ 4 (Keyed|Unkeyed|SingleValue) (En|De)codableContainer 4 σʔλΛอ࣋͠ɺϓϩύςΟͷ ม׵ํ๏Λఏڙ͢Δ 4 Codableͷ఩ֶʮΤϯίʔσΟ ϯάͷৄࡉΛΧϓηϧԽʯͷମ ݱऀ 14
  15. KeyedDecodingContainer 15

  16. UnkeyedDecodingContainer 16

  17. SingleValueDecodingContainer 17

  18. ͋ͱɺܕͱͯ͠͸ Keyed... Unkeyed... ͕ͩɺ໾ׂͱͯ͠ Nested Containers ͱ͍͏ͷ΋͋Δ 18

  19. ֤Containerͷ ࢖͍ಓ 19

  20. struct Hoge: Decodable { struct Fuga: Codable { let id:

    Int } let fuga: Fuga } ͋ΔJSONσʔλΛ struct Hoge ! ( Obejct Hoge -> Object Fuga -> Int id ) ΁ͱdecode͢Δࡍͷɺ ɾinputͱͯ͠ظ଴͞ΕΔJSON ɾinitͷίʔυ Λ͓ݟͤ͠·͢ɻ 20
  21. JSON: Object -> Object -> Value { "fuga": { "id":

    1 } } 21
  22. { "fuga": { "id": 1 } } !KeyedDecodingContainer Ͱdecode͢Δ init(from

    decoder: Decoder) throws { let container = try decoder .container(keyedBy: CodingKeys.self) fuga = try container.decode(Fuga.self, forKey: .fuga) } 22
  23. JSON: Array -> Object -> Value [ { "id": 1

    } ] 23
  24. [ { "id": 1 } ] !UnkeyedDecodingContainer Ͱdecode͢Δ init(from decoder:

    Decoder) throws { var container = try decoder.unkeyedContainer() fuga = try container.decode(Fuga.self) } UnkeyedDecodingContainer ͸ [1,2] ! CGPoint(x: 1, y: 2) ͳͲʹ΋࢖ΘΕΔ 24
  25. JSON: Object -> Value { "fuga": 1 } 25

  26. { "fuga": 1 } !SingleDecodingContainer Ͱdecode͢Δ init(from decoder: Decoder) throws

    { let container = try decoder.container(keyedBy: CodingKeys.self) fuga = try container.decode(Fuga.self, forKey: .fuga) } // !͸ KeyedDecodingContainer ͱಉ͡Ͱɺ // "͕ͬͪ͜มΘΔ struct Fuga: Codable { let id: Int init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() id = try container.decode(Int.self) } } 26
  27. JSON: Object -> Object -> Object -> Value { "hoge":

    { "fuga": { "id": 1 } } } 27
  28. { "hoge": { "fuga": { "id": 1 } } }

    !Nested Container (ࠓճ͸Keyed) Ͱdecode͢Δ ※ྫͱͯ͠ॻ͍͍ͯΔ͚ΕͲɺHogeͷσίʔυͷͨΊʹ౉͢JSON͕͜ͷߏ଄ͳͷ͸ྑ͘ͳ͍ͱࢥ͏ private enum HogeCodingKey: CodingKey { case hoge } init(from decoder: Decoder) throws { let container = try decoder .container(keyedBy: HogeCodingKey.self) .nestedContainer(keyedBy: CodingKeys.self, forKey: .hoge) fuga = try container.decode(Fuga.self, forKey: .fuga) } 28
  29. ͳ͓ɺܧঝؔ܎ͷදݱʹ΋ Nested Container Λ࢖͏΂͖ͩͦ͏Ͱ͢ superDecoder ͸ɺNested Container( "super" ͱ͍͏ΩʔܾΊଧͪ) ͷDecoderɻ

    { "bestFriend": {}, "super": { "legCount": 88 } } 29
  30. Ͳ͏΍ͬͯ࢖͍ಓͷద੾͞Λ೺Ѳ ͔ͨ͠ 4 WWDCͷηογϣϯΛؤுͬͯฉ͘ 4 ඪ४తͳॻ͖ํ͸ https://github.com/ apple/swift ͷιʔείʔυΛݕࡧ͢Ε͹೺ ѲͰ͖Δ

    4 େମͷܕ͸Codableʹద߹͍ͯ͠ΔͷͰ 30
  31. ͨͱ͑͹ URL ͷιʔε https://github.com/apple/swift/blob/c5ff1f2cac8da6a14330f4b033b94c7c926d2126/ stdlib/public/SDK/Foundation/URL.swift#L1210-L1236 extension URL : Codable {

    private enum CodingKeys : Int, CodingKey { case base case relative } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let relative = try container.decode(String.self, forKey: .relative) let base = try container.decodeIfPresent(URL.self, forKey: .base) guard let url = URL(string: relative, relativeTo: base) else { throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Invalid URL string.")) } self = url } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self.relativeString, forKey: .relative) if let base = self.baseURL { try container.encode(base, forKey: .base) } } } 31
  32. decodingͱvalidation ͷ౷߹ 32

  33. Codable Philosophy 4 Error handling built-in 4 ૊Έࠐ·ΕͨΤϥʔ੍ޚ 4 Encapsulate

    encoding details 4 ΤϯίʔσΟϯάͷৄࡉΛΧϓηϧԽ 4 Abstract format from type 4 ந৅Խ͞ΕͨϑΥʔϚοτ 33
  34. Error handling built-in SwiftͷܕγεςϜͰ͸දݱ͖͠Εͳ͍ υϝΠϯݻ༗ͷόϦσʔγϣϯΛ ΠχγϟϥΠζ࣌ʹ࣮ߦՄೳ 34

  35. σίʔυͷϑΣʔζ 1. σίʔυ 1. όΠτσʔλ 2. ߏ଄Λ࣋ͭόΠτσʔλ (JSON౳) 3. ܕ෇͚͞Εͨσʔλ(Swift

    ͷܕ) 2. όϦσʔγϣϯ 1. Domain-specific validation 2. Graph-level validation 35
  36. 36

  37. Domain-specific validation΋ initʹؚΊΒΕΔ 37

  38. ·ͱΊ: init(from:) ͷॻ͖ํ ɾContainerΛద੾ʹ࢖͍෼͚Δ ɾదٓDomain-specific validation΋ؚΊΔ ɾॻ͖ํʹ໎ͬͨΒެࣜϦϙδτϦΛݟΔ 38