PKCanvasView size error

Here is the implementation.

import SwiftUI
import PencilKit

struct DrawingCanvas_bug: UIViewRepresentable {
    typealias UIViewType = PKCanvasView
    private let toolPicker = PKToolPicker()
    
    @Binding var drawing: PKDrawing
    var isOpaque: Bool = true
    var drawingDidChange: ((PKDrawing) -> Void)?
    
    func makeUIView(context: Context) -> PKCanvasView {
        let canvasView = PKCanvasView(frame: .zero)
        canvasView.drawing = drawing
        canvasView.delegate = context.coordinator
        canvasView.backgroundColor = .clear
        canvasView.isOpaque = isOpaque
        canvasView.alwaysBounceVertical = true

        //  The size of the canvas is Zero, so I cannot update the ZoomScale now.
        // context.coordinator.updateZoomScale(for: canvasView)
        
        toolPicker.setVisible(true, forFirstResponder: canvasView)
        toolPicker.addObserver(canvasView)
        canvasView.becomeFirstResponder()

        return canvasView
    }
    
    func updateUIView(_ canvasView: PKCanvasView, context: Context) {
        DispatchQueue.main.async {
            // We can get the correct ZoomScale and the correct ContentSize, but part of the drawing is not visible.
            // Using the select tool can select them.
            context.coordinator.updateZoomScale(for: canvasView)
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    static func dismantleUIView(_ canvasView: PKCanvasView, coordinator: Coordinator) {
        canvasView.resignFirstResponder()
    }
}

extension DrawingCanvas_bug {
    class Coordinator: NSObject, PKCanvasViewDelegate {
        var host: DrawingCanvas_bug
        init(_ host: DrawingCanvas_bug) {
            self.host = host
        }
        
        func canvasViewDrawingDidChange(_ canvasView: PKCanvasView) {
            host.drawing = canvasView.drawing
            if let action = host.drawingDidChange {
                action(canvasView.drawing)
            }
            updateContentSizeForDrawing(for: canvasView)
        }
        
        func updateZoomScale(for canvasView: PKCanvasView) {
            let canvasScale = canvasView.bounds.width / 768
            canvasView.minimumZoomScale = canvasScale
            canvasView.maximumZoomScale = canvasScale
            canvasView.zoomScale = canvasScale
            updateContentSizeForDrawing(for: canvasView)
        }
        
        func updateContentSizeForDrawing(for canvasView: PKCanvasView) {
            let drawing = canvasView.drawing
            let contentHeight: CGFloat
            
            if !drawing.bounds.isNull {
                contentHeight = max(canvasView.bounds.height, (drawing.bounds.maxY + 500) * canvasView.zoomScale)
            } else {
                contentHeight = canvasView.bounds.height
            }
            canvasView.contentSize = CGSize(width: 768 * canvasView.zoomScale, height: contentHeight)
        }
    }
}

And here is how I use:

NavigationSplitView(columnVisibility: .constant(.doubleColumn)) {
    List(selection: $selection) {
        ForEach(drawingModel.drawings, id: \.uuidString) {
            DrawingRow(drawingData: $0)
        }
    }
} detail: {
    DrawingView()
}
.navigationSplitViewStyle(.balanced) // <- If I use automatic style, PKCanvasView's size is correct
Answered by LiYanan04818 in 725359022

I'm sorry for consuming network resources. I have FIXED this issue!

Accepted Answer

I'm sorry for consuming network resources. I have FIXED this issue!

PKCanvasView size error
 
 
Q