Supporting SwiftUI with Core Graphics

Nov 22 2022 Swift 5.5, iOS 15, Xcode 13

Part 1: Supporting SwiftUI with Core Graphics

3. Host a UIView in a SwiftUI View

Episode complete

Play next episode

Next
Save for later
About this episode
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 2. Create a CGImage Next episode: 4. Build a UIKit Drawing Pad

This video Host a UIView in a SwiftUI View was last updated on Nov 22 2022

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

You can unlock the rest of this video course, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.

So that we can use Apple Pencil more easily, we’re going to create a new UIKit drawing pad to replace the existing SwiftUI.

App Architecture

In our app, the existing DrawingPadView will host DrawingPadRepresentation and our ColorPicker controls. CanvasView will be a UIView where the user draws. DrawingPadRepresentation will be the intermediary between DrawingPadView and CanvasView

DrawingPadView.swift

The drawing pad view is currently set up to show the SwiftUI drawing pad. It has nearly everything we need to swap in the new UIKit drawing pad. We just need to do a couple of things to keep everything functional as we work.

@State var drawing: UIImage?

ContentView.swift

You’ll have an error now over in ContentView.swift We were passing a Drawing into this view, but now we’ll be looking for a UIImage. So, just remove this argument for now.

DrawingPadView(❌drawing: cellStore.selectedCell?.drawing❌)

CanvasView.swift

Now we’re ready to get started on our UIKit drawing pad. There will be several new files involved, so, start by setting up a group.

import UIKit
class CanvasView: UIControl {
}
  var drawingImage: UIImage?
  var color: UIColor = .black

  init(color: UIColor, drawingImage: UIImage?) {
    self.drawingImage = drawingImage
    self.color = color
    super.init(frame: .zero)
  }
required init?(coder: NSCoder) {
  fatalError("init(coder:) has not been implemented")
}

DrawingPadRepresentation.swift

Now to get this interfacing with SwiftUI, we need our intermediary. Create a new Swift file called DrawingPadRepresentation.swift.

import SwiftUI
struct DrawingPadRepresentation: UIViewRepresentable {
}
  @Binding var drawingImage: UIImage?
  let color: UIColor
func makeUIView(context: Context) -> CanvasView {
  let view = CanvasView(color: color,
                        drawingImage: drawingImage)
  return view
}
func updateUIView(_ uiView: CanvasView, context: Context) {
  uiView.color = color
}
class Coordinator: NSObject {
  @Binding var drawingImage: UIImage?
  
  init(drawingImage: Binding<UIImage?>) {
    _drawingImage = drawingImage
  }
}
@objc func drawingImageChanged(_ sender: CanvasView) {
  self.drawingImage = sender.drawingImage
}
func makeCoordinator() -> Coordinator {
  Coordinator(drawingImage: $drawingImage)
}
view.addTarget(
  context.coordinator,
  action: #selector(Coordinator.drawingImageChanged(_:)),
  for: .valueChanged)

CanvasView.swift

Open CanvasView and add a method that the view will call when the user finishes his stroke.

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  sendActions(for: .valueChanged)
}

DrawingPadView.swift

In DrawingPadView, we’ll add a new DrawingPadRepresentation right where the old swiftUI drawing pad used to be.

DrawingPadRepresentation(drawingImage: $drawing, color: pickedColor.uiColor)