Supporting SwiftUI with Core Graphics

Nov 22 2022 · Swift 5.5, iOS 15, Xcode 13

Part 1: Supporting SwiftUI with Core Graphics

03. Host a UIView in a SwiftUI View

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 02. Create a CGImage Next episode: 04. Build a UIKit Drawing Pad

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

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

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)