CtrlK
BlogDocsLog inGet started
Tessl Logo

thiennc-tesoglobal/ios-skills

Community-maintained Agent Skills for complete Swift and Apple-platform app delivery.

72

Quality

90%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Medium

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

SKILL.mdskills/pencilkit/

name:
pencilkit
description:
Implement drawing, handwriting, and sketching with PencilKit and PaperKit. Use when integrating PKCanvasView, configuring PKToolPicker, handling drawing gestures and Apple Pencil features, inspecting or rendering strokes, managing drawing data, or building drawing interfaces.

PencilKit

Integrate drawing, sketching, and annotation into iOS and iPadOS apps using PencilKit (PKCanvasView, PKToolPicker, PKDrawing) and PaperKit. Targets Swift 6.3 / iOS 26+.

Contents

  • Core PencilKit Architecture
  • SwiftUI Integration Pattern
  • Drawing Persistence and Data
  • Input Policy and Gestures
  • Route by Task
  • Common Mistakes
  • Review Checklist
  • References

Core PencilKit Architecture

ComponentResponsibility
PKCanvasViewScrollable drawing canvas that receives touch and pencil inputs; inherits from UIScrollView
PKToolPickerFloating system tool palette offering pens, pencils, markers, erasers, rulers, and custom tools
PKDrawingImmutable data model containing vector strokes (PKStroke), stroke points, and bounds
PKToolActive drawing instrument (PKInkingTool, PKEraserTool, PKLassoTool)
PKCanvasViewDelegateNotifies when drawing changes or user starts/ends drawing

SwiftUI Integration Pattern

Bridge PKCanvasView into SwiftUI using UIViewRepresentable:

import SwiftUI
import PencilKit

struct CanvasViewRepresentable: UIViewRepresentable {
    @Binding var drawing: PKDrawing
    var tool: PKTool = PKInkingTool(.pen, color: .black, width: 5)
    var isRulerActive: Bool = false

    func makeUIView(context: Context) -> PKCanvasView {
        let canvas = PKCanvasView()
        canvas.drawingPolicy = .anyInput
        canvas.tool = tool
        canvas.isRulerActive = isRulerActive
        canvas.delegate = context.coordinator
        return canvas
    }

    func updateUIView(_ uiView: PKCanvasView, context: Context) {
        if uiView.drawing != drawing {
            uiView.drawing = drawing
        }
        uiView.tool = tool
        uiView.isRulerActive = isRulerActive
    }

    func makeCoordinator() -> Coordinator { Coordinator(self) }

    class Coordinator: NSObject, PKCanvasViewDelegate {
        var parent: CanvasViewRepresentable
        init(_ parent: CanvasViewRepresentable) { self.parent = parent }

        func canvasViewDrawingDidChange(_ canvasView: PKCanvasView) {
            Task { @MainActor in parent.drawing = canvasView.drawing }
        }
    }
}

Drawing Persistence and Data

  • Serialization: Serialize drawings using drawing.dataRepresentation(). Restore via PKDrawing(data:).
  • Image Generation: Render drawings to raster images with drawing.image(from: canvasView.bounds, scale: canvasView.traitCollection.displayScale).
  • Stroke Inspection: Iterate through drawing.strokes to inspect points, pressure, force, and azimuth.

Input Policy and Gestures

Configure canvasView.drawingPolicy:

  • .default: Follows system preference (Apple Pencil only if configured in Settings).
  • .anyInput: Allows finger drawing alongside Apple Pencil.
  • .pencilOnly: Restricts drawing strictly to Apple Pencil; finger touches scroll the canvas.

Coordinating PKToolPicker: Attach the picker with toolPicker.setVisible(true, forFirstResponder: canvasView) and toolPicker.addObserver(canvasView). Ensure the canvas becomes first responder.

Route by Task

  • For tracking tool picker changes, visibility, and frame obstruction, read Tool Picker Observer Pattern.
  • For custom items in PKToolPicker (iOS 18+), read Custom Tool Picker Items.
  • For stroke construction, comparison, and shape recognition, read Constructing Strokes Programmatically.
  • For thumbnail generation and background image rendering, read Thumbnail Generation.
  • For undo/redo coordination with UndoManager, read Undo/Redo Support.

Common Mistakes

  • Forgetting to call canvasView.becomeFirstResponder() before showing PKToolPicker.
  • Updating SwiftUI @Binding var drawing continuously during drawing gestures, causing hitching and feedback loops.
  • Overriding finger scrolling gestures without setting drawingPolicy = .pencilOnly.
  • Generating high-resolution raster images synchronously on the main thread from complex drawings.
  • Assuming PKToolPicker floats automatically in SwiftUI without anchoring to a window or first responder.

Review Checklist

  • PKCanvasView embedded in SwiftUI with a clean Coordinator
  • drawingPolicy explicitly set (.anyInput, .pencilOnly, or .default)
  • PKToolPicker tied to canvas first responder and visible state
  • Drawing data serialized with dataRepresentation() and restored with error handling
  • Raster image rendering performed asynchronously or off the main thread for large canvases
  • Undo and redo actions integrated with the canvas's undoManager
  • Dynamic Type and safe area insets respected when PKToolPicker obscures canvas regions

References

skills

.mcp.json

README.md

tile.json