Decodable - Pairs Taiwan

Ca8210ff0ece2bb6f9fff5fd0770ea64?s=47 Muukii
June 15, 2017

Decodable - Pairs Taiwan

Ca8210ff0ece2bb6f9fff5fd0770ea64?s=128

Muukii

June 15, 2017
Tweet

Transcript

  1. 2.

    About Me ‣ muukii <Hiroshi Kimura> ‣ iOS Senior Engineer

    at eureka, Inc. ‣ Pairs Taiwan iOS ‣ GitHub : @muukii ‣ https://about.me/muukii ☕ ⌚
  2. 3.
  3. 4.

    Agenda ‣ WWDC17 ‣ Swift4 - Codable - Decodable -

    Customize & DecodingError ‣ Pairs Taiwan iOS Development ‣ muukii/StackScrollView
  4. 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)
  5. 7.

    ‣ Too many JSON libraries ‣ SwiftyJSON/SwiftyJSON ‣ muukii/JAYSON ‣

    and more. and more. Can We Replace JSON Libraries?
  6. 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) } }
  7. 10.

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

    catch let error as DecodingError { } catch { } Error Handling JSONDecoder throw DecodingError
  8. 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): }
  9. 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
  10. 14.

    { "age" : 18, "state" : { "isFavorite" : false

    } } struct User: Decodable { struct State: Decodable { let isFavorite: String } let state: State } .typeMismatch
  11. 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
  12. 16.

    .valueNotFound { "age" : null, "name" : "muukii" } struct

    User: Decodable { let age: Int let name: String } User.age is required
  13. 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
  14. 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"
  15. 21.
  16. 23.

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

    muukii/StackScrollView • Module (Request, Service, Component, App) • MVVM with RxSwift • Carthage & CocoaPods • and more…
  17. 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
  18. 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])
  19. 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
  20. 28.

    Features class StackScrollView { func append(view: UIView) func remove(view: UIView,

    animated: Bool)
 func scroll(to view: UIView, animated: Bool) }
  21. 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 {}
  22. 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.
  23. 31.