Share
Embed
気遣いの 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
Yuka Ezura
September 01, 2018
Transcript
52 slides
-
• ezura • ׆ಈ • try!Swift Tokyo • iOSDC •
mockmock radio • αʔΫϧ: Swift প • Work at LINE !2 -
Agenda • ෳͷྻڍࢠͷ associated value ΛಉҰࢹ͢Δ • Optional ͷଶ •
Closure Ͱ͢ΔରΛม͑Δ • ॳظઃఆͷ 3 ͭͷํ๏ !5 -
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 -
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 -
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 -
case .comic(_, let content), .novel(let content): return content case .comic(_,
let content): return content case .novel(let content): return content !10 ҟͳΔͷͱͯ͠ѻ͏ ಉҰࢹ͢Δ -
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 -
·ͱΊ !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 Ͱ࠶ղې) ಉ͡ม໊, ܕ ϥϕϧͷ༗ແ໊લແؔ -
if let book = book { … } guard let
book = book else { … } book?.method book!.method book ?? defaultValue ... !14 -
if let book = book, case .comic(let tag) = book
{ ... } !15 Optional -
!17 if let book = book, case .comic(let tag) =
book { ... } if case .comic(let tag)? = book { ... } -
if let book = book, case .comic(let tag) = book
{ ... } if case .comic(let tag)? = book { ... } !18 -
guard let item = item else { return nil }
return OtherModel(item) !19 ඇ Optional ΛҾʹͱΔؔ/initializer Optional -
guard let item = item else { return nil }
return OtherModel(item) !20 return item?.asOtherModel() `OtherModel` ͷ function `Item` ͷ function -
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 -
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 -
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 Ͱ͔Γ͍͢ • ෳࡶͳঢ়ଶͰ៉ྷʹ·ͱΊΒΕΔ • ୯७ͳॲཧΛ؆ܿʹදݱՄೳ • ෳࡶͳঢ়گΛ·ͱΊΑ͏ͱ͢Δͱ ಡΈʹ͘͘ͳΔ -
·ͱΊ !24 if let book = book { … }
guard let book = book else { … } book?.method book!.method book ?? defaultValue case .comic? = book { … } book.map { … } / book.flatMap { … } -
if /* condition */ { titleLabel.text = "All good!" }
else if /* condition */ { titleLabel.text = "Warning" } else { titleLabel.text = nil } !26 ݅ذͯ͠Δ titleLabel ͷ text Λઃఆͯ͠Δ ͜͜ titleLabel.text ͷઃఆ શ෦ͦ͏ͩ titleLabel ʹදࣔ͢ΔςΩετΛ݅Ԡͯ͡ઃఆ͢Δ ඞͣԿ͔ઃఆ͢Δ -
titleLabel.text = { if /* condition */ { return "All
good!" } else if /* condition */ { return "Warning" } else { return nil } }() !27 titleLabel ʹදࣔ͢ΔςΩετΛઃఆ͢Δ ඞͣԿ͔ઃఆ͢Δ (ྫ֎ൃੜআ͘) ݅ذͯ͠Δ -
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 ͷઃఆΛڧௐ • ඞͣԿΒ͔ͷ͕ઃఆ͞ΕΔ͜ͱͷอূ είʔϓΛ۠ΕΔ -
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 -
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 -
(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 -
(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? ؔ࿈ੑ͕ऑ͍ -
(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 : ؔ࿈ͷڧ͍ͷಉ࢜ʹ͢Δ -
let confirmButton = UIButton() confirmButton.backgroundColor = .white confirmButton.setImage(⬛, for: .normal)
confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center !35 -
let confirmButton = UIButton() confirmButton.backgroundColor = .white confirmButton.setImage(⬛, for: .normal)
confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center !36 -
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 -
let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white confirmButton.setImage(⬛,
for: .normal) confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center } ํ๏ 2 !38 จͷ۠ΕΛ໌ࣔ είʔϓΛ۠Δ `do` • είʔϓ͕۠ΕΔ • ॲཧΛηΫγϣϯ͚Ͱ͖Δ • ϒϩοΫͰͷԾͷΠϯελϯε͕ෆཁ • ܕͷ߹ɺ`var` ࢦఆ͕ඞਢ • ϒϩοΫͷ్தͰൈ͚͍ͨ߹ɺ Մಡੑ͕ѱ͘ͳΔ -
var text = "value"; do { text.append(suffix) ... } ํ๏
2 !39 ܕͷ߹ɺ มߋՃ͑Δ߹ʹ mutable ੑඞਢ • είʔϓ͕۠ΕΔ • ॲཧΛηΫγϣϯ͚Ͱ͖Δ • ϒϩοΫͰͷԾͷΠϯελϯε͕ෆཁ • ܕͷ߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ߹ɺ Մಡੑ͕ѱ͘ͳΔ -
let confirmButton = UIButton(); ready: do { confirmButton.backgroundColor = .white
guard true /* condition */ else { break ready } ... } ํ๏ 2 !40 • είʔϓ͕۠ΕΔ • ॲཧΛηΫγϣϯ͚Ͱ͖Δ • ϒϩοΫͰͷԾͷΠϯελϯε͕ෆཁ • ܕͷ߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ߹ɺ Մಡੑ͕ѱ͘ͳΔ -
let confirmButton = UIButton(); do { confirmButton.backgroundColor = .white confirmButton.setImage(⬛,
for: .normal) confirmButton.imageView?.clipsToBounds = false confirmButton.imageView?.contentMode = .center } ํ๏ 2 !41 จͷ۠ΕΛ໌ࣔ είʔϓΛ۠ΔͨΊͷ `do` • είʔϓ͕۠ΕΔ • ॲཧΛηΫγϣϯ͚Ͱ͖Δ • ϒϩοΫͰͷԾͷΠϯελϯε͕ෆཁ • ܕͷ߹ɺ`var` ࢦఆ͕ඞཁ • ϒϩοΫͷ్தͰൈ͚͍ͨ߹ɺ Մಡੑ͕ѱ͘ͳΔ -
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 ͕ෳࡶͳ߹ɺݟ௨͕͠ѱ͍ -
@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 ܕαϙʔτ -
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 -
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 Ͱ࠶ղې) ಉ͡ม໊, ܕ ϥϕϧͷ༗ແ໊લແؔ -
Optional ͷଶ !48 if let book = book { …
} guard let book = book else { … } book?.method book!.method book ?? defaultValue case .comic? = book { … } book.map { … } / book.flatMap { … } -
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 Ͱ͢ΔରΛม͑Δ -
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 -
Capture list Autolayout Interface builder tips ૉΒ͖͠ enum ඞम protocol
ศརίϚϯυ Swift4.2 attributes !51