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

Conditional Contents in SwiftUI

Conditional Contents in SwiftUI

SwiftUIでの条件分岐使うTips

83d400bf204ff2a10a1ee934287f0a9d?s=128

Yasuharu Yanamura

August 27, 2019
Tweet

Transcript

  1. Conditional Content in SwiftUI Potatotips #64 2019/8/27 Yasuharu Yanamura

  2. ࣗݾ঺հ • Yasuharu Yanamura/༄ଜ ߁੖ • ɹ@yanamura_ɹɹ@yanamura • ίωώτגࣜձࣾ •

    ϚϚϦiOSΞϓϦ։ൃ
  3. 2020/2 potatotips #69 ίωώτͰ։࠵༧ఆʂ

  4. + if / switch

  5. ৚݅ͰViewΛग़͠෼͚͍ͨ ͱ͍͏ͱ͖͕ͨ·ʹ͋Δ

  6. • ͜͏ॻ͘ͱɾɾɾ var body: some View { if imageName.isEmpty {

    return Text("no image") } else { return Image(imageName) } } ৚݅෼ذͰViewΛग़͠෼͚
  7. • ίϯύΠϧΤϥʔʂ var body: some View { if imageName.isEmpty {

    return Text("no image") } else { return Image(imageName) } } ! Function declares an opaque return type, but the return statements in its body do not have matching underlying types ৚݅෼ذͰViewΛग़͠෼͚
  8. var body: some View { if imageName.isEmpty { return Text("no

    image") } else { return Image(imageName) } } ! Function declares an opaque return type, but the return statements in its body do not have matching underlying types 0QBRVF3FTVMU5ZQF ͳͷͰͭͷܕΛฦ͞ ͳ͍ͱ͇
  9. var body: some View { if imageName.isEmpty { return Text("no

    image") } else { return Text(imageName) } } ಉ͡ܕΛฦ͢ͳΒ0,
  10. ղܾํ๏

  11. ৚݅෼ذΛ࢖͏ํ๏ 1 • Group / HStack / VStack / ZStack

    var body: some View { Group { if imageName.isEmpty { Text("no image") } else { Image(imageName) } } }
  12. ৚݅෼ذΛ࢖͏ํ๏ 2 • @ViewBuilder @ViewBuilder var body: some View {

    if imageName.isEmpty { Text("no image") } else { Image(imageName) } }
  13. ৚݅෼ذΛ࢖͏ํ๏ 3 • ViewBuilder.buildEither() var body: some View { imageName.isEmpty

    ? ViewBuilder.buildEither(first: Text("no image")) : ViewBuilder.buildEither(second: Image(imageName)) }
  14. ͲΕΛ࢖ͬͯ΋ViewBuilderͷԸܙ

  15. ͳͥViewBuilderΛ࢖͏ͱ ղܾ͢Δͷ͔

  16. ViewBuilderͷ࢓૊Έ • ViewBuilder͸function builderͰ࣮૷ • function builder͸ίϯύΠϧ࣌ʹifจͷchainͩͬͨΒ buildEither(first:), buildEither(second:)Λ͔ͭ͏

  17. ͭ·Γ @ViewBuilder var body: some View { if imageName.isEmpty {

    Text("Hello") } else { Image(imageName) } } var body: some View { imageName.isEmpty ? ViewBuilder.buildEither(first: Text("no image")) : ViewBuilder.buildEither(second: Image(imageName)) }
  18. ViewBuilderͷbuildEither • _ConditionalContent<TrueContent,FalseContent>Λฦ͢ extension ViewBuilder { public static func buildEither<TrueContent,

    FalseContent>(first: TrueContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View public static func buildEither<TrueContent, FalseContent>(second: FalseContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View }
  19. ֬ೝͯ͠ΈΔ @ViewBuilder var body: some View { if imageName.isEmpty {

    Text("Hello") } else { Image(imageName) } } _ConditionalContent<Text, Image> • ໭Γ஋
  20. ͳͥViewBuilderΛ࢖͏ͱ ղܾ͢Δͷ͔ ↓ ViewBuilder͕৚݅෼ذΛ _ConditionalContent<,>ʹͯ͠Δ

  21. ͔͠͠

  22. ݱ࣌఺Ͱ͸NGͳέʔε • ❌ switch / if case / if let

    ... var body: some View { Group { switch foo { case a: Text("a") case b: Text("b") case c: Text("c") } } } ※@ViewBuilderΛ࢖͏ͱίϯύΠϧ͸௨Δ͕ಈ͔ͳ͍
  23. ݱ࣌఺Ͱ͸NGͳέʔε • ❌ switch / if case / if let

    ... var body: some View { Group { switch foo { case a: Text("a") case b: Text("b") case c: Text("c") } } } var body: some View { Group { if foo == .a { Text("a") } else if foo == .b { Text("b") } else if foo == .c { Text("c") } } } • ⭕ if / else if /else
  24. Ͳ͏ͯ͠΋if / else Ҏ֎͕࢖͍͍ͨ • AnyViewʹ͢Ε͹ͳΜͱ͔ͳΔ!? var body: some View

    { switch foo { case .a: return AnyView(Text("a")) case .b: return AnyView(Text("b")) case .c: return AnyView(Text("c")) } }
  25. ·ͱΊ • ViewBuilderͷྗͰView಺Ͱ৚݅෼ذ͕࢖͑Δ • ͨͩ͠if / else ͷΈ • ࠷ѱAnyViewΛ࢖͑͹if

    elseҎ֎΋ɾɾ
  26. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

  27. Appendix

  28. ifͷΈ

  29. ViewBuilderͷ࢓૊Έ • function builder͸ίϯύΠϧ࣌ʹifจ୯ମ(chainͳ͠)ͩͬͨΒ buildIf()Λ͔ͭ͏

  30. ͭ·Γ @ViewBuilder var body: some View { if !imageName.isEmpty {

    Image(imageName) } } var body: some View { ViewBuilder.buildIf( !imageName.isEmpty ? Image(imageName) : nil ) }
  31. ViewBuilderͷbuildIf • Content?Λฦ͢ extension ViewBuilder { public static func buildIf<Content>(_

    content: Content?) -> Content? where Content : View }
  32. ৚݅෼ذͳ͠

  33. ViewBuilderͷ࢓૊Έ • buildBlock()Λ͔ͭ͏

  34. ͭ·Γ @ViewBuilder var body: some View { Text("Hello") Image(imageName) }

    var body: some View { ViewBuilder.buildBlock( Text("Hello"), Image(imageName) ) }
  35. ViewBuilderͷbuildBlock • Ҿ਺(ཁૉ)ͷ਺͕ෳ਺ͷ৔߹TupleView<(,...,)>Λฦ͢ extension ViewBuilder { public static func buildBlock<C0,

    C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0 : View, C1 : View public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where C0 : View, C1 : View, C2 : View, C3 : View, C4 : View, C5 : View, C6 : View, C7 : View, C8 : View, C9 : View } <<ུ>>
  36. ֬ೝͯ͠ΈΔ @ViewBuilder var body: some View { Text("Hello") Image(systemName: "circle")

    } TupleView<(Text, Image)> • ໭Γ஋