$30 off During Our Annual Pro Sale. View Details »

Conditional Contents in SwiftUI

Conditional Contents in SwiftUI

SwiftUIでの条件分岐使うTips

Yasuharu Yanamura

August 27, 2019
Tweet

More Decks by Yasuharu Yanamura

Other Decks in Technology

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)> • ໭Γ஋