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

気遣いの iOS プログラミング

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Yuka Ezura Yuka Ezura
September 01, 2018

気遣いの iOS プログラミング

iosdc2018
Speaker deck だとリンクがクリックできないので、ここに貼ります!

## associated value の章
バグが見つかり一時的に禁止: https://github.com/apple/swift/commit/bf71ec85995b1a7fc26c811eae4a7a99504654d5

解決済み: https://github.com/apple/swift/commit/f5f715f8ffd6c6deed0637ff0013890947feb506

## map / flatMap
https://github.com/apple/swift/blob/c66e136c18fc4146c7ef3eb52f5e534245b34a1c/stdlib/public/core/Optional.swift#L166

Avatar for Yuka Ezura

Yuka Ezura

September 01, 2018
Tweet

More Decks by Yuka Ezura

Other Decks in Programming

Transcript

  1. • ezura • ׆ಈ • try!Swift Tokyo • iOSDC •

    mockmock radio • αʔΫϧ: Swift প • Work at LINE !2
  2. Agenda • ෳ਺ͷྻڍࢠͷ associated value ΛಉҰࢹ͢Δ • Optional ΁ͷଶ౓ •

    Closure Ͱ஫໨͢Δର৅Λม͑Δ • ॳظઃఆͷ 3 ͭͷํ๏ !5
  3. enum Book { case comic(tag: Tag, content: Content) case novel(content:

    Content) var content: Content { switch self { case .comic(_, let content): return content case .novel(let content): return content } } } !7 associated value
  4. enum Book { case comic(tag: Tag, content: Content) case novel(content:

    Content) var content: Content { switch self { case .comic(_, let content): return content case .novel(let content): return content } } } !8 associated value
  5. enum Book { case comic(tag: Tag, content: Content) case novel(content:

    Content) var content: Content { switch self { case .comic(_, let content), .novel(let content): return content } } } !9 associated value
  6. case .comic(_, let content), .novel(let content): return content case .comic(_,

    let content): return content case .novel(let content): return content !10 ҟͳΔ΋ͷͱͯ͠ѻ͏ ಉҰࢹ͢Δ
  7. enum APIError { case networkError(NetworkError) case authError(AuthError) } … switch

    apiError { case .networkError(let error as Error), .authError(let error as Error): // do something // use `error` as `Error` // do something } όά͕ݟ͔ͭΓҰ࣌తʹېࢭ: https://github.com/apple/swift/commit/bf71ec85995b1a7fc26c811eae4a7a99504654d5
 ղܾࡁΈ: https://github.com/apple/swift/commit/f5f715f8ffd6c6deed0637ff0013890947feb506 ໌ࣔతͳ Cast Ͱ࢖༻Մೳʹ
 (Xcode10 Ͱ෮׆) !11
  8. ·ͱΊ !12 enum Enum { case simple(TypeA) case complex(TypeA, TypeB)

    case empty } ... switch e { case .simple(let ): // do something // use `` case .complex(let , _): // do something // use `` case .empty: // do something } switch e { case .simple(let ), .complex(let , _): // do something // use `` case .empty: // do something } • ஋ΛಉҰࢹ͢Δʁ͠ͳ͍ʁ • ܕ͕ҟͳΔͱ͖͸໌ࣔతʹܕΛࢦఆ͢Δ 
 (Xcode10 Ͱ࠶ղې) ಉ͡ม਺໊, ܕ ϥϕϧͷ༗ແ΍໊લ͸ແؔ܎
  9. if let book = book { … } guard let

    book = book else { … } book?.method book!.method book ?? defaultValue ... !14
  10. !17 if let book = book, case .comic(let tag) =

    book { ... } if case .comic(let tag)? = book { ... }
  11. if let book = book, case .comic(let tag) = book

    { ... } if case .comic(let tag)? = book { ... } !18
  12. guard let item = item else { return nil }

    return OtherModel(item) !19 ඇ Optional ΛҾ਺ʹͱΔؔ਺/initializer Optional
  13. guard let item = item else { return nil }

    return OtherModel(item) !20 return item?.asOtherModel() `OtherModel` ͷ function `Item` ͷ function
  14. guard let item = item else { return nil }

    return OtherModel(item) return item.map { OtherModel($0) }
 return item.flatMap { OtherModel($0) }
 //return item.map(OtherModel.init) !21 Value map / flatMap
  15. guard let item = item else { return nil }

    return OtherModel(item) return item.map { OtherModel($0) }
 return item.flatMap { OtherModel($0) }
 Value map / flatMap Optional<Optional<OtherModel>> Optional<Item> Optional<OtherModel> Optional<OtherModel> Optional<OtherModel> https://github.com/apple/swift/blob/c66e136c18fc4146c7ef3eb52f5e534245b34a1c/stdlib/public/core/Optional.swift#L166
  16. guard let item = item, let obj = obj else

    { return nil } return OtherModel(arg1: item, arg2: obj) return item.map { OtherModel($0) }
 return item.flatMap { OtherModel($0) }
 //return item.map(OtherModel.init) !23 • ໌ࣔతͳ unwrap Ͱ෼͔Γ΍͍͢ • ෳࡶͳঢ়ଶͰ΋៉ྷʹ·ͱΊΒΕΔ • ୯७ͳॲཧΛ؆ܿʹදݱՄೳ • ෳࡶͳঢ়گΛ·ͱΊΑ͏ͱ͢Δͱ
 ಡΈʹ͘͘ͳΔ
  17. ·ͱΊ !24 if let book = book { … }

    guard let book = book else { … } book?.method book!.method book ?? defaultValue case .comic? = book { … } book.map { … } / book.flatMap { … }
  18. if /* condition */ { titleLabel.text = "All good!" }

    else if /* condition */ { titleLabel.text = "Warning" } else { titleLabel.text = nil } !26 ৚݅෼ذͯ͠Δ titleLabel ͷ text Λઃఆͯ͠Δ ͜͜΋ titleLabel.text ͷઃఆ શ෦ͦ͏ͩ titleLabel ʹදࣔ͢ΔςΩετΛ৚݅Ԡͯ͡ઃఆ͢Δ
 ඞͣԿ͔ઃఆ͢Δ
  19. titleLabel.text = { if /* condition */ { return "All

    good!" } else if /* condition */ { return "Warning" } else { return nil } }() !27 titleLabel ʹදࣔ͢ΔςΩετΛઃఆ͢Δ
 ඞͣԿ͔ઃఆ͢Δ (ྫ֎ൃੜআ͘) ৚݅෼ذͯ͠Δ
  20. if true /* condition */ { titleLabel.text = "All good!"

    } else if true /* condition */ { titleLabel.text = "Warning" } else { titleLabel.text = nil } titleLabel.text = { if true /* condition */ { return "All good!" } else if true /* condition */ { return "Warning" } else { return nil } }() !28 ৚݅ʹԠͯ͡Կ͔͢Δ͜ͱΛڧௐ • titleLabel.text ΁ͷઃఆΛڧௐ • ඞͣԿΒ͔ͷ஋͕ઃఆ͞ΕΔ͜ͱͷอূ είʔϓΛ۠੾ΕΔ
  21. if /* condition */ { titleLabel.text = "All good!" subtitleLabel.text

    = "You can use all service." } else if /* condition */ { titleLabel.text = "Warning" subtitleLabel.text = "Please check your acount." } else { titleLabel.text = nil subtitleLabel.text = nil } !29
  22. titleLabel.text = { if /* condition */ { return "All

    good!" } else if /* condition */ { return "Warning" } else { return nil } }() subtitleLabel.text = { if /* condition */ { return "You can use all service." } else if /* condition */ { return "Please check your acount." } else { return nil } }() !30
  23. (titleLabel.text, subtitleLabel.text) = { if /* condition */ { return

    (title: "All good!", subtitle: "You can use all service.") } else if /* condition */ { return (title: "Warning", subtitle: "Please check your acount.") } else { return (title: nil, subtitle: nil) } }() !31
  24. (titleLabel.text, x) = { if /* condition */ { return

    (title: "Good!", x: 0) } else if /* condition */ { return (title: "Better", x: maxRect.minX) } else { return (title: nil, x: maxRect.maxX) } }() !32 titile? x? ؔ࿈ੑ͕ऑ͍
  25. (titleLabel.text, subtitleLabel.text) = { if /* condition */ { return

    (title: "All good!", subtitle: "You can use all service.") } else if /* condition */ { return (title: "Warning", subtitle: "Please check your acount.") } else { return (title: nil, subtitle: nil) } }() !33 ஫: ؔ࿈ͷڧ͍΋ͷಉ࢜ʹ͢Δ
  26. let confirmButton = UIButton() confirmButton.backgroundColor = .white confirmButton.setImage(⬛, for: .normal)

    confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center !35
  27. let confirmButton = UIButton() confirmButton.backgroundColor = .white confirmButton.setImage(⬛, for: .normal)

    confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center !36
  28. let confirmButton: UIButton = { let button = UIButton() button.backgroundColor

    = .white button.setImage(⬛, for: .normal) button.imageView?.clipsToBounds = false button.imageView?.contentMode = .center return button }() ํ๏ 1 !37 • ൚༻త͔ͭҰൠత • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ઃఆର৅ͷม਺Λ `let` ʹͰ͖Δ ΠϯελϯεΛ࡞Δ ׬੒ͨ͠ΠϯελϯεΛฦ͢ ஋ܕͷ৔߹Ͱ΋ `let` Ͱ OK
  29. let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white confirmButton.setImage(⬛,

    for: .normal) confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center } ํ๏ 2 !38 จͷ۠੾ΕΛ໌ࣔ είʔϓΛ۠੾Δ `do` • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ϒϩοΫ಺ͰͷԾͷΠϯελϯε͕ෆཁ • ஋ܕͷ৔߹ɺ`var` ࢦఆ͕ඞਢ • ϒϩοΫͷ్தͰൈ͚͍ͨ৔߹ɺ
 Մಡੑ͕ѱ͘ͳΔ
  30. var text = "value"; do { text.append(suffix) ... } ํ๏

    2 !39 ஋ܕͷ৔߹ɺ
 มߋՃ͑Δ৔߹ʹ mutable ੑඞਢ • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ϒϩοΫ಺ͰͷԾͷΠϯελϯε͕ෆཁ • ஋ܕͷ৔߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ৔߹ɺ
 Մಡੑ͕ѱ͘ͳΔ
  31. let confirmButton = UIButton(); ready: do { confirmButton.backgroundColor = .white

    guard true /* condition */ else { break ready } ... } ํ๏ 2 !40 • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ϒϩοΫ಺ͰͷԾͷΠϯελϯε͕ෆཁ • ஋ܕͷ৔߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ৔߹ɺ
 Մಡੑ͕ѱ͘ͳΔ
  32. let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white confirmButton.setImage(⬛,

    for: .normal) confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center } ํ๏ 2 !41 จͷ۠੾ΕΛ໌ࣔ είʔϓΛ۠੾ΔͨΊͷ `do` • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ϒϩοΫ಺ͰͷԾͷΠϯελϯε͕ෆཁ • ஋ܕͷ৔߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ৔߹ɺ
 Մಡੑ͕ѱ͘ͳΔ
  33. let confirmButton = with(UIButton()) { button in button.backgroundColor = .white

    button.setImage(⬛, for: .normal) button.imageView?.clipsToBounds = false button.imageView?.contentMode = .center } ํ๏ 3 !42 • είʔϓ͕۠੾ΕΔ • ॲཧΛηΫγϣϯ෼͚Ͱ͖Δ • ઃఆର৅ͷม਺Λ࠷ऴతʹ `let` ʹͰ͖Δ • Closure ಺ͰͷԾͷΠϯελϯεએݴ͕ෆཁ • initializer ͕ෳࡶͳ৔߹ɺݟ௨͕͠ѱ͍
  34. @discardableResult func with<T>(_ item: T, update: (inout T) throws ->

    Void) rethrows -> T { var this = item try update(&this) return this } ํ๏ 3 !43 ग़య: 
 Swift Style, Second Edition by Erica Sadun https://pragprog.com/book/esswift2/swift-style-second-edition ஋ܕ΋αϙʔτ
  35. let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white }

    let confirmButton: UIButton = { let button = UIButton() button.backgroundColor = .white return button }() let confirmButton = with(UIButton()) { button in button.backgroundColor = .white } Initialize !44 Immediately Invoked Closures do-block Custom function
  36. Handling associated value !47 enum Enum { case simple(TypeA) case

    complex(TypeA, TypeB) case empty } ... switch e { case .simple(let ): // do something // use `` case .complex(let , _): // do something // use `` case .empty: // do something } switch e { case .simple(let ), .complex(let , _): // do something // use `` case .empty: // do something } • ஋ΛಉҰࢹ͢Δʁ͠ͳ͍ʁ • ܕ͕ҟͳΔͱ͖͸໌ࣔతʹܕΛࢦఆ͢Δ 
 (Xcode10 Ͱ࠶ղې) ಉ͡ม਺໊, ܕ ϥϕϧͷ༗ແ΍໊લ͸ແؔ܎
  37. Optional ΁ͷଶ౓ !48 if let book = book { …

    } guard let book = book else { … } book?.method book!.method book ?? defaultValue case .comic? = book { … } book.map { … } / book.flatMap { … }
  38. if true /* condition */ { titleLabel.text = "All good!"

    } else if true /* condition */ { titleLabel.text = "Warning" } else { titleLabel.text = nil } titleLabel.text = { if true /* condition */ { return "All good!" } else if true /* condition */ { return "Warning" } else { return nil } }() !49 ৚݅ʹԠͯ͡Կ͔͢Δ͜ͱΛڧௐ • titleLabel.text ΁ͷઃఆΛڧௐ • ඞͣԿΒ͔ͷ஋͕ઃఆ͞ΕΔ͜ͱͷอূ είʔϓΛ۠੾ΕΔ Closure Ͱ஫໨͢Δର৅Λม͑Δ
  39. let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white }

    let confirmButton: UIButton = { let button = UIButton() button.backgroundColor = .white return button }() let confirmButton = with(UIButton()) { button in button.backgroundColor = .white } Initialize !50 Immediately Invoked Closures do-block Custom function