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

Decodable - Pairs Taiwan

Ca8210ff0ece2bb6f9fff5fd0770ea64?s=47 Muukii
June 15, 2017

Decodable - Pairs Taiwan

Ca8210ff0ece2bb6f9fff5fd0770ea64?s=128

Muukii

June 15, 2017
Tweet

Transcript

  1. Decodable - Pairs Taiwan @muukii - eureka, Inc Twitter :

    #eureka_meetup
  2. About Me ‣ muukii <Hiroshi Kimura> ‣ iOS Senior Engineer

    at eureka, Inc. ‣ Pairs Taiwan iOS ‣ GitHub : @muukii ‣ https://about.me/muukii ☕ ⌚
  3. None
  4. Agenda ‣ WWDC17 ‣ Swift4 - Codable - Decodable -

    Customize & DecodingError ‣ Pairs Taiwan iOS Development ‣ muukii/StackScrollView
  5. typealias Codable = Decodable & Encodable Swift4

  6. Decodable • JSONDecoder [ { "name" : "muukii", "age" :

    18, "state" : { "isFavorite" : false }, "flags" : ["a", "b", "c"] }, … … ] struct User: Decodable { struct State: Decodable { let isFavorite: Bool } let name: String let age: Int let state: State let flags: [String] } let decoder = JSONDecoder() let users = try decoder.decode([User].self, from: data)
  7. ‣ Too many JSON libraries ‣ SwiftyJSON/SwiftyJSON ‣ muukii/JAYSON ‣

    and more. and more. Can We Replace JSON Libraries?
  8. Custom Decoding struct User: Decodable { private enum CodingKeys: String,

    CodingKey { case name = "username" case age case flags } let name: String let age: Int let flags: [String] init(from decoder: Decoder) throws { let c = try decoder.container(keyedBy: CodingKeys.self) name = try c.decode(String.self, forKey: .name) age = try c.decode(Int.self, forKey: .age) flags = try c.decode([String].self, forKey: .flags) } }
  9. More https://developer.apple.com/documentation/foundation/archives_and_serialization/ using_json_with_custom_types Sample Code
 Using JSON with Custom Types

  10. do { let users = try decoder.decode([User].self, from: data) }

    catch let error as DecodingError { } catch { } Error Handling JSONDecoder throw DecodingError
  11. DecodingError let error: DecodingError switch error { case .keyNotFound(let key,

    let context): case .typeMismatch(let type, let context): case .valueNotFound(let type, let context): case .dataCorrupted(let context): }
  12. .keyNotFound struct User: Decodable { let age: Int let name:

    String } { "name" : "muukii" }
  13. case .keyNotFound(let key, let context): print(key) // age print(context.debugDescription) //

    Key not found when expecting non-optional type A for coding key "age" print(context.codingPath.map { $0?.stringValue }) // [nil, Optional("age")] Root -> age .keyNotFound
  14. { "age" : 18, "state" : { "isFavorite" : false

    } } struct User: Decodable { struct State: Decodable { let isFavorite: String } let state: State } .typeMismatch
  15. case .typeMismatch(let type, let context): print(type) // String print(context.debugDescription) //

    Expected to decode String but found a number instead. print(context.codingPath.map { $0?.stringValue }) // [nil, Optional("state"), Optional("isFavorite")] .typeMismatch Root -> state -> isFavorite
  16. .valueNotFound { "age" : null, "name" : "muukii" } struct

    User: Decodable { let age: Int let name: String } User.age is required
  17. .valueNotFound case .valueNotFound(let type, let context): print(type) // Int print(context.debugDescription)

    // Found null value when expecting non-optional type UInt for coding key "age" print(context.codingPath.map { $0?.stringValue }) // [nil, Optional("age")] Root -> age
  18. .dataCorrupted struct Image: Decodable { let url: URL } {

    "url" : "" }
  19. case .dataCorrupted(let context): print(context.debugDescription) // Invalid URL string. print(context.codingPath.map {

    $0?.stringValue }) // [nil] Root -> age .dataCorrupted
  20. Summary ‣ Decodable is useful ‣ Simple code for simple

    mappings ‣ Possible custom mapping ‣ DecodingError indicates useful information ‣ KeyPath on caused error ‣ "notFoundKey", "valueNotFound", "keyMismatch" , "dataCorrupted"
  21. None
  22. 02 - Global

  23. Used techniques • No Interface Builder • TextureGroup/Texture (AsyncDisplayKit) •

    muukii/StackScrollView • Module (Request, Service, Component, App) • MVVM with RxSwift • Carthage & CocoaPods • and more…
  24. StackScrollView

  25. What is StackScrollView? • iOS Form UI Builder • Doesn't

    use UITableViewCell / UICollectionViewCell • UIView based Cell • Initialization is faster than UIStackView • No built-in UI-Components • No longer need to consider reusing Cells • Self-sizing with AutoLayout • Nothing is impossible
  26. Usage StackScrollView let view = StackScrollView() let cell_1 = LabelStackCell()

    view.append(views: [cell_1]) let cell_2 = LabelStackCell() view.append(views: [cell_2]) let cell_3 = LabelStackCell() view.append(views: [cell_3])
  27. Usage StackScrollView final class LabelStackCell: UIView { let label =

    UILabel() init() { super.init(frame: .zero) addSubview(label) label <- Edges(16) // nakiostudio/EasyPeasy } } Label UIView must have sufficient internal constraints
  28. Features class StackScrollView { func append(view: UIView) func remove(view: UIView,

    animated: Bool)
 func scroll(to view: UIView, animated: Bool) }
  29. Features protocol StackCellType : class { } extension StackCellType where

    Self : UIView { var stackScrollView: StackScrollView? { get } func scrollToSelf(animated: Bool) func updateLayout(animated: Bool) func remove() } Recalculate size of view extension LabelStackCell : StackCellType {}
  30. Summary ‣ Helpful APIs for Form UI ‣ No longer

    need to consider reusing Cells ‣ Nothing is impossible ‣ We can create custom UI for Our Products.
  31. Thank you