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

SwiftUIでUIViewを使うときのレイアウト処理 / Layout process when using UIKit view in SwiftUI

Mike Apurin
December 17, 2021

SwiftUIでUIViewを使うときのレイアウト処理 / Layout process when using UIKit view in SwiftUI

Mike Apurin

December 17, 2021
Tweet

More Decks by Mike Apurin

Other Decks in Technology

Transcript

  1. SwiftUIͰUIViewΛ࢖͏ͱ͖ͷ ϨΠΞ΢τॲཧ Apurin Mikhail @ YUMEMI.swift #14

  2. ࣗݾ঺հ Apurin Mikhail ΞϓϦϯɾϛϋΠϧ auramagi apurin.me 􀒡 - ΏΊΈͷiOSΤϯδχΞ -

    ࠓݱࡏϩγΞ͔ΒϦϞʔτϫʔΫ - ژ౎ → ϞεΫϫͷఱؾΪϟοϓ͸͙͍͑ (+13° → -17°) - ିग़ͷM1 Max MacBook Proಧ͘௚લʹߦͬͨͷ͕੯͍͠
  3. ࠓ೥ͷৼΓฦΓ ͳΜͱͳ͘SwiftUIΛ৮Δػձ͕ଟ͔ͬͨҰ೥ͩͬͨ - UIKitͷҊ݅ͰϓϨϏϡʔΛಋೖ - iOS 13.0·ͰҾ্͖͛Δ४උ - σϞΞϓϦ౳ͷ࡞੒ -

    ΏΊΈࣾ಺ͷSwiftUIษڧձ։࠵ - ݸਓ։ൃ 🥰
  4. SwiftUIͰUIKitͷϏϡʔ͕࢖͍͍ͨ - εΫϥονͷҊ݅Ͱ͸ͳ͍ͳΒɺ஥ྑ͘ڞଘ͢Δඞཁ͕͋Δ - Apple͕४උ͞Ε͍ͯΔ΋ͷΛ࢖͑͹Ͱ͖Δ - UIView → UIViewRepresentable -

    UIViewController → UIViewControllerRepresentable
  5. struct LabelRepresentable: UIViewRepresentable { let text: String func makeUIView(context: Context)

    -> UILabel { .init() } func updateUIView(_ uiView: UILabel, context: Context) { uiView.numberOfLines = 0 uiView.text = text } } UIViewRepresentableΛॻ͍ͯΈΔ ؆୯ʹॻ͚·͢ʂ ඞਢϝιου: - Ϗϡʔੜ੒ makeUIView - Ϗϡʔߋ৽ updateUIView
  6. struct LabelRepresentable_Previews: PreviewProvider { static var previews: some View {

    LabelRepresentable( text: "Journey before destination" ) } } ΍ͬͨʂ ɻɻɻ Μʁ தԝἧ͑ʹͳ͍ͬͯͳ͍ʂʂ PreviewͰ࢖ͬͯΈΔ
  7. struct LabelRepresentable_Previews: PreviewProvider { static var previews: some View {

    LabelRepresentable( text: "Journey before destination" ) .border(.red) .padding() } } ը໘શମͷαΠζΛऔ͍ͬͯΔ SwiftUI ͷ Text ͷΑ͏ʹɺͽͬͨΓͷαΠζΛͱͬͯ
 தԝἧ͑ʹͳΔΠϝʔδ͕ͩͬͨɺ·͍͍͔͋ʁ PreviewͰ࢖ͬͯΈΔ
  8. struct LabelRepresentable_Previews: PreviewProvider { static var previews: some View {

    LabelRepresentable( text: "To love the journey is to accept no such 
 end. I have found, through painful experience, 
 that the most important step a person can take 
 is always the next one." ) .border(.red) .padding() } } PreviewͰ࢖ͬͯΈΔ Ξ ͩΊͩʔ orz
  9. SwiftUIͷϨΠΞ΢τॲཧ WWDC 2019 — Building Custom Views with SwiftUI ͦ΋ͦ΋SwiftUIͰͲ͏΍ͬͯҐஔͱαΠζ͕


    ܾΊΒΕΔͷ͔ʁ ϨΠΞ΢τॲཧͷৄࡉ͸ඇެ։ͳͷͰ
 υΩϡϝϯτ͕΄΅ͳ͍ 😔 جຊͷॲཧ͸ҎԼͷεςοϓ͔ΒͳΔ 1. ਌View͕ࢠViewʹαΠζΛఏҊ͢Δ 2. ࢠView͕ࣗ෼ͷαΠζΛܾΊΔ 3. ਌View͕ࣗ෼ͷ࠲ඪۭؒͰࢠViewΛ഑ஔ͢Δ
  10. SwiftUIͷϨΠΞ΢τॲཧ ViewͷαΠζ͸࣍ͷܗʹͳ͍ͬͯΔͱਪଌͰ͖Δ struct Dimension { let min: CGFloat let ideal:

    CGFloat let max: CGFloat } - min: ࠷௿஋ - ideal: ཧ૝αΠζ - max: ࠷ߴ஋ - ؔ܎Λݫक: min <= ideal <= max
  11. SwiftUIͷϨΠΞ΢τॲཧ ఏҊαΠζ͸࣍ͷܗͰ౉͞ΕΔͱਪଌͰ͖Δ struct ProposedSize { let width: CGFloat? let height:

    CGFloat? } - ஋͕ࢦఆ͞Ε͍ͯΔ৔߹͸ɺͦΕΛϕʔεʹαΠζΛܭࢉ - nilͷ৔߹͸ɺViewࣗ਎ͷidealαΠζΛͱΔ - . fi xedSizeͰnilʹมߋ͞ΕΔ
  12. SwiftUIͷϨΠΞ΢τॲཧ ௨ৗͷ৔߹͸ɺҎԼͷܭࢉ͕ࣜదԠ͞ΕΔ if let proposedWidth = proposedSize.width { // dimensionsͰ্ݶ஋ɾԼݶ஋Λ཈͑Δ

    width = max( dimensions.min, min(dimensions.max, proposedWidth) ) } else { width = dimensions.ideal } // height΋ಉ༷
  13. Color.mint .frame( minWidth: 100, maxWidth: 200, minHeight: 100, maxHeight: 200

    ) .frame(width: 300, height: 300) .border(.mint) SwiftUIͷϨΠΞ΢τॲཧ 📱 W: 390 H: 763 .frame(minWidth: 200, …) .frame(width: 300, height: 300) Color ఏҊαΠζ ࣮αΠζ W: 300 H: 300 W: 200 H: 200 W: 300 H: 300 W: 200 H: 200 W: 200 H: 200
  14. Text("Hello YUMEMI.swift") .fixedSize() .border(.mint) .frame(width: 300, height: 300) .border(.mint) SwiftUIͷϨΠΞ΢τॲཧ

    📱 W: 390 H: 763 .fixedSize() .frame(width: 300, height: 300) Text("Hello YUMEMI.swift") ఏҊαΠζ ࣮αΠζ W: 300 H: 300 W: nil H: nil W: 300 H: 300 W: 149.7 H: 20.3 W: 149.7 H: 20.3
  15. UIKitͱͷޓ׵ੑ Ͱ͸ɺͦͷॲཧͰͲ͏΍ͬͯUIViewͷαΠζ͕ܾΊΒΕΔʁ • SwiftUIଆͷϥούʔ͕Α͠ͳʹ΍ͬͯ͘ΕΔʢʣ • UIViewRepresentable • UIViewControllerRepresentable • ͦΕͧΕͷڍಈ͕ҧ͏

  16. UIViewRepresentable AutoLayoutͷintrinsicαΠζͱpriorityΛݩʹͯ͠αΠζΛܭࢉ Intrinsic size Compression Resistance Hugging ݁Ռ
 (min …

    ideal … max) (-1) - - 0 … 0 … ∞ x < 750 < 750 0 … x … ∞ x < 750 >= 750 0 … x … x x < 750 < 750 x … x … ∞ x >= 750 >= 750 x … x … x -1 = UIView.noIntrinsicMetric 750 = UILayoutPriority.defaultHigh
  17. UIViewRepresentable 1. AutoLayoutͷϓϩύςΟ͔ΒUIView͕औΕΔαΠζΛܾఆ 2. ී௨ͷܭࢉࣜͰɺఏҊ͞ΕͨαΠζ͔Β࣮αΠζΛܭࢉ 3. UIViewͷ invalidateIntrinsicContentSize() ͕ݺ͹ΕͨΒ΍Γ௚͠

  18. UIViewRepresentable 1 ͱ 2 ͷڍಈ͸ௐ੔Ͱ͖Δඇެ։API͕͋Δ ⚠ ඇެ։APIͳͷͰϦϦʔεϏϧυʹೖΕͪΌμϝ ⚠ public protocol

    UIViewRepresentable { // 1 (AutoLayoutϓϩύςΟ → ͳΕΔαΠζ) func _overrideLayoutTraits( _ layoutTraits: inout SwiftUI._LayoutTraits, for uiView: Self.UIViewType ) // 2 (ఏҊαΠζ → ࣮αΠζ) func _overrideSizeThatFits( _ size: inout CoreGraphics.CGSize, in proposedSize: SwiftUI._ProposedSize, uiView: Self.UIViewType ) }
  19. UIViewControllerRepresentable UIViewRepresentableͱൺ΂ͯɺௐ੔Ͱ͖Δ͜ͱ͕গͳ͍ • preferredContentSize ͰidealαΠζΛࢦఆՄೳ • ҎԼͷViewαΠζ͕ܾఆ͞ΕΔ • 0 …

    preferredContentSize … ∞
  20. import RepresentableKit struct UILabel_Previews: PreviewProvider { static var previews: some

    View { UIViewAdaptor { let view = UILabel() view.numberOfLines = 0 view.text = "To love the journey is to accept no 
 such end. I have found, through painful experience, that the most important step a person can take is always the next one." return view } .padding() } } RepresentableKitͷ঺հ UIViewRepresentableͷαΠζܭࢉΛந৅Խͯ͠
 ΑΓ؆୯ʹ࢖͑ΔΑ͏ʹϔϧύʔϥΠϒϥϦΛ
 ࡞Γ·ͨ͠ɻ
 https://github.com/yumemi-inc/RepresentableKit
  21. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠