UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

PencilKit with SwiftUI

Forums > SwiftUI

Hi all,

I was trying to figure out how to get a UIViewRepresentable of a PKCanvasView to work in SwiftUI with the ability for a parent view to manage undo and redo functionality. I spent a few days of research and found a solution that seems to work well. I wanted to post this here in case this can help someone in the future!

Here's the parent view that uses the environment UndoManager:

struct Writer: View {
    @Environment(\.undoManager) private var undoManager
    @State private var canvasView = PKCanvasView()

    var body: some View {
        VStack(spacing: 10) {
            Button("Clear") {
                canvasView.drawing = PKDrawing()
            }
            Button("Undo") {
                undoManager?.undo()
            }
            Button("Redo") {
                undoManager?.redo()
            }
            MyCanvas(canvasView: $canvasView)
        }
    }
}

Here's the PKCanvasView wrapped UIViewRepresentable:

struct MyCanvas: UIViewRepresentable {
    @Binding var canvasView: PKCanvasView

    func makeUIView(context: Context) -> PKCanvasView {
        canvasView.drawingPolicy = .anyInput
        canvasView.tool = PKInkingTool(.pen, color: .black, width: 15)
        return canvasView
    }

    func updateUIView(_ canvasView: PKCanvasView, context: Context) { }
}

Initially I tried various things using coordinators and PKCanvasViewDelegate functions. In the end, the solution is very simple and straightforward. In hindsight, I feel almost foolish for how long it took me to get this working. Hopefully this will prevent a future headache for someone else!

edit: I found that my original solution broke with iOS 14. Adding canvasView.drawingPolicy = .anyInput seemed to have fixed the problem.

18      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.