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

Let's Coding SwiftUI on iPad!

Let's Coding SwiftUI on iPad!

第11回 HAKATA.swift x Swift愛好会~福岡と東京のSwift勉強会コラボ~
https://hakata-swift.connpass.com/event/149988/

Yutaro Muta

January 25, 2020
Tweet

More Decks by Yutaro Muta

Other Decks in Programming

Transcript

  1. Let's Coding SwiftUI on iPad!
    2020/01/21 @HAKATA.swift vol.11
    Yutaro Muta @yutailang0119

    View Slide

  2. • Yutaro Muta @yutailang0119
    • Hatena Co., Ltd. @Kyoto
    • Conference Staff
    • builderscon 2020
    • try! Swift Tokyo 2020
    • and more
    Who am I ?

    View Slide

  3. Goal
    • iPadͰίʔσΟϯά͢ΔΑ͏ʹͳΔ
    • ͍࣋ͬͯͳ͍ਓ͸iPadΛങͬͯؼΔ
    • SwiftUIͷViewʹ͍ͭͯɺͪΐͬͱ஌Δ

    View Slide

  4. What's Swift Playgrounds?

    View Slide

  5. What's Swift Playgrounds?
    • iPadΞϓϦ Swift Playground
    • Document: https://developer.apple.com/documentation/swift_playgrounds
    • ϝΠϯϢʔε͸ɺϓϩάϥϛϯάڭҭΒ͍͠

    View Slide

  6. What's Swift Playgrounds?
    • iOSΞϓϦ։ൃͱ͍ۙ͠ػೳ͕ଟ͘࢖͑Δ
    • UIKit (Xcode Playground)
    • Camera
    • Bluetooth
    • AR (SceneKit)
    • SwiftUI ΋࢖͑Δʂʂʂʂʂ
    • Swift Playgrounds 3.1: Build with the SwiftUI framework in new playgrounds you create

    View Slide

  7. Run SwiftUI on Swift Playgrounds

    View Slide

  8. Run SwiftUI on Swift Playgrounds
    import SwiftUI
    import PlaygroundSupport
    struct ContentView: View {
    var body: some View {
    VStack {
    Text("Hello")
    .font(.largeTitle)
    .foregroundColor(.primary)
    Text("world")
    .font(.title)
    .foregroundColor(.secondary)
    }
    }
    }
    let host = UIHostingController(rootView: ContentView())
    PlaygroundPage.current.liveView = host

    View Slide

  9. Run SwiftUI on Swift Playgrounds

    View Slide

  10. Run Swift Playgrounds file
    on Xcode

    View Slide

  11. Run Swift Playgrounds file on Xcode
    • PlaygroundsͷStarting Pointʹ Xcode PlaygroundΛબ୒͢Δ
    • ֦ுࢠ͕ .playgroundͱͯ͠࡞੒͞ΕΔ (্هҎ֎ͩͱ .playgroundbook)
    -> XcodeͷPlaygroundͰ΋࣮ߦ͕Ͱ͖Δ
    • ٯʹɺXcodeͰ࡞੒ͨ͠ .playground ΋Swift PlaygroundsͰ࣮ߦՄೳ

    View Slide

  12. Run Swift Playgrounds file on Xcode

    View Slide

  13. Pros/Cons of Swift Playgrounds

    View Slide

  14. Pros of Swift Playgrounds
    • iPadͰखܰʹίʔυ͕ॻ͚Δ
    • Foundation΋SwiftUI΋ͦΕҎ֎ͷFramework΋ѻ͑Δ
    • ΦϑϥΠϯͰ࣮ߦՄೳ

    View Slide

  15. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ

    View Slide

  16. ͓͠·͍

    View Slide

  17. ⚡͔͜͜Βຊฤ⚡

    View Slide

  18. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ

    View Slide

  19. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ
    <- AppleཔΉ

    View Slide

  20. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ
    <- AppleཔΉ

    View Slide

  21. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ
    <- AppleཔΉ

    View Slide

  22. Cons of Swift Playgrounds
    • Xcodeʹൺ΂ΔͱɺΤσΟλ͸෺଍Γͳ͍
    • ίϯύΠϧ
    • ૣ͘͸ͳ͍
    • XcodeͷSwiftUI Canvas͸ͳ͍
    • ຖճ࣮ߦ͕ඞཁ
    • UIHostingControllerʹೖΕͨ1ͭViewΛ஫ࢹ͢Δ͜ͱʹͳΔ
    ^
    |
    Ͳ͏ʹ͔Ͱ͖ͦ͏

    View Slide

  23. yutailang0119/LayoutInspector
    ໊લ͸෇͚͍ͯΔ͚Ͳɺ·ͩͰ͖ͯͳ͍

    View Slide

  24. LayoutInspector

    View Slide

  25. LayoutInspector
    import SwiftUI
    struct LayoutInspector: View {
    private let _body: Body
    private let color: Color
    init(body: Body,
    color: Color? = nil) {
    self._body = body
    self.color = color ?? Color.random
    }
    var body: some View {
    ZStack(alignment: .topLeading) {
    self._body
    .layoutPriority(1.0)
    self._label
    }
    .border(color)
    }
    private var _label: some View {
    Text(String(describing: type(of: _body)))
    .lineLimit(1)
    .font(.footnote)
    .foregroundColor(.primary)
    .background(color.opacity(0.7))
    }
    }
    import SwiftUI
    extension SwiftUI.View {
    func layoutInspector(color: Color? = nil) -> some View {
    LayoutInspector(body: self,
    color: color)
    }
    }

    View Slide

  26. LayoutInspector

    View Slide

  27. ׬ᘳ

    View Slide

  28. < ViewModifier protocolʹ
    ४ڌ͢ΔͱΑͦ͞͏ͩΑ

    View Slide

  29. ViewModifier
    • https://developer.apple.com/documentation/swiftui/viewmodifier
    > A modifier that you apply to a view or another view modifier, producing a
    different version of the original value.
    • ModifiedContent ΍ View.modifier(_:) ͱ૊Έ߹Θͤͯ࢖͏

    View Slide

  30. Custom ViewModifier
    import SwiftUI
    struct PrimaryLabel: ViewModifier {
    func body(content: Content) -> some View {
    content
    .padding()
    .background(Color.red)
    .foregroundColor(Color.white)
    .font(.largeTitle)
    }
    }
    HACKING WITH Swift: How to create custom modifiers
    https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-custom-modifiers

    View Slide

  31. Extension SwiftUI.View
    import SwiftUI
    extension SwiftUI.View {
    func labelPrimary() -> some View {
    self
    .modifier(PrimaryLabel())
    }
    }

    View Slide

  32. Custom ViewModifier

    View Slide

  33. ͳΔ΄ͲɺΑͦ͞͏ͩ

    View Slide

  34. ݁࿦͔Βݴ͏ͱɺେมͩͬͨ

    View Slide

  35. ModifierΛ࡞ͬͯɺ
    ಺෦ͰLayoutInspectorΛ࢖ͬͯΈΔ

    View Slide

  36. LayoutInspectModifier (α)
    struct LayoutInspectModifier: ViewModifier {
    private let color: Color?
    init(color: Color? = nil) {
    self.color = color
    }
    public func body(content: Content) -> some View {
    LayoutInspector(body: content,
    color: color)
    }
    }

    View Slide

  37. LayoutInspectModifier (α)

    View Slide

  38. _ViewModifier_Content
    LayoutInspectModifier (α)

    View Slide

  39. ViewModifierͷ࣮૷
    • func body(content: Self.Content) -> Self.Body
    • Gets the current body of the caller.
    • Discussion
    • content is a proxy for the view that will have the modifier represented by Self applied to it.
    • typealias ViewModifier.Content
    • The content view type.

    View Slide

  40. ViewModifierͷ࣮૷
    • ViewModifier.Content ͸ɺݩͷViewͦͷ΋ͷͰ͸ͳ͘ɺProxy
    • contentʹ type(of:) Λ͔͚ͯ΋ɺݩͷViewͷType͸Θ͔Βͳ͍

    View Slide

  41. OMG

    View Slide

  42. ࡞ઓมߋ
    • ModifierΛ෼͚Δ
    • ֎࿮ͱ೚ҙͷϥϕϧΛ෇͚Δ LayoutInspectModifier
    • ֎࿮Λ෇͚ͭͭɺType໊Λදࣔ͢Δ TypeNameLayoutInspectModifier

    View Slide

  43. LayoutInspecterΛมߋ

    View Slide

  44. LayoutInspecter
    import SwiftUI
    struct LayoutInspector: View {
    private let _body: Body
    private let label: String
    private let color: Color
    init(body: Body,
    label: String,
    color: Color? = nil) {
    self._body = body
    self.label = label
    self.color = color ?? Color.random
    }
    var body: some View {
    ZStack(alignment: .topLeading) {
    self._body
    .layoutPriority(1.0)
    self._label
    }
    .border(color)
    }
    private var _label: some View {
    Text(label)
    .lineLimit(1)
    .font(.footnote)
    .foregroundColor(.primary)
    .background(color.opacity(0.7))
    }
    }

    View Slide

  45. LayoutInspectModifier

    View Slide

  46. LayoutInspectModifier
    import SwiftUI
    struct LayoutInspectModifier: ViewModifier {
    private let color: Color?
    private let label: String
    init(color: Color? = nil,
    label: String = "") {
    self.color = color
    self.label = label
    }
    func body(content: Content) -> some View {
    LayoutInspector(body: content,
    label: label,
    color: color)
    }
    }

    View Slide

  47. TypeNameLayoutInspectModifier

    View Slide

  48. TypeNameLayoutInspectModifier
    import SwiftUI
    struct TypeNameLayoutInspectModifier: ViewModifier {
    private let color: Color?
    private let _body: V
    init(color: Color? = nil, body: V) {
    self.color = color
    self._body = body
    }
    func body(content: Content) -> some View {
    LayoutInspector(body: content,
    label: String(describing: type(of: _body)),
    color: color)
    }
    }

    View Slide

  49. ModifierΛద༻͢Δextension
    import SwiftUI
    extension SwiftUI.View {
    func layoutInspector(color: Color? = nil, label: String = "") -> some View {
    self
    .modifier(LayoutInspectModifier(color: color,
    label: label))
    }
    func typeNameLayoutInspector(color: Color? = nil) -> some View {
    self
    .modifier(TypeNameLayoutInspectModifier(color: color,
    body: self))
    }
    }

    View Slide

  50. ࣮ߦʂ

    View Slide

  51. ࣮ߦʂ

    View Slide

  52. Αͦ͞͏

    View Slide

  53. ࣮͸·ͩམͱ͕݀͠...

    View Slide

  54. contentView.frame()

    View Slide

  55. ViewModifierΛܦ༝͢ΔViewʹ
    TypeNameLayoutInspectModifier͸
    ΍ͬͺΓյΕΔ

    View Slide

  56. ࠓ೔͸͜͜·Ͱ

    View Slide

  57. ·ͱΊ

    View Slide

  58. ·ͱΊ
    • iPad͚ͩͰ΋ɺSwiftɺSwiftUIΛॻ͘͜ͱ͸Ͱ͖Δ
    • yutailang0119/LayoutInspector ͸ɺ΋͏ͪΐͬͱ࿅͖ͬͯ·͢
    • LayoutInspectModifier୯ମͷΞϓϩʔν͸ѱ͘ͳͦ͞͏
    • Swift Playgroundsͷ༻్͚ͩͰͳ͘ɺΞϓϦέʔγϣϯ։ൃͷσόοΨ
    ͱͯ͠ൃల͍ͤͨ͞
    • ྫ͑͹ɺShake GestureΛरͬͯɺදࣔ/ඇදࣔΛ੾Γସ͑Δ౳

    View Slide

  59. Reference
    • https://yutailang0119.hatenablog.com/entry/swiftui-with-swift-playgrounds
    • https://www.apple.com/swift/playgrounds/
    • https://developer.apple.com/documentation/swift_playgrounds
    • https://developer.apple.com/xcode/swiftui/
    • https://tech.d-itlab.co.jp/programming/1052/
    • https://developer.apple.com/documentation/swiftui/viewmodifier
    • https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-custom-modifiers

    View Slide

  60. &OKPZ4XJGU1MBZHSPVOET 5IBOLT
    w NVUBZVUBSP!HNBJMDPN
    w IUUQTUXJUUFSDPNZVUBJMBOH
    w IUUQTHJUIVCDPNZVUBJMBOH

    View Slide