Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2026 SwiftUI & UI FrameworksApp Services

WWDC26 · 8 min · SwiftUI & UI Frameworks / App Services

Unwrap PaperKit

Craft a canvas-based application with PaperKit. Explore the new data model APIs that let you access, create, and modify markup elements. Learn how to add custom controls and annotations, and discover best practices for integrating these features into your app to build a fully featured creative canvas.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 6 snippets

Creating markup subelements swift · at 1:36 ↗
import PaperKit

func generateMarkup(pageSize: CGSize, panelFrames: [CGRect], configuration: ShapeConfiguration) -> PaperMarkup {
    var markup = PaperMarkup(bounds: CGRect(origin: .zero, size: pageSize))
    var subelements: MarkupOrderedSet = markup.subelements
    for panelFrame: CGRect in panelFrames {
        let shape = ShapeMarkup(frame: panelFrame, configuration: configuration)
        subelements.append(shape)
    }
    markup.subelements = subelements
    return markup
}
Making template elements read-only swift · at 3:03 ↗
import PaperKit

func generateMarkup(pageSize: CGSize, panelFrames: [CGRect], configuration: ShapeConfiguration) -> PaperMarkup {
    var markup = PaperMarkup(bounds: CGRect(origin: .zero, size: pageSize))
    var subelements: MarkupOrderedSet = markup.subelements
    for panelFrame: CGRect in panelFrames {
        var shape = ShapeMarkup(frame: panelFrame, configuration: configuration)
        shape.allowedInteractions = .readOnly
        subelements.append(shape)
    }
    markup.subelements = subelements
    return markup
}
Apply style to template elements swift · at 4:22 ↗
import PaperKit

func updatePanelColor(_ selectedColor: CGColor) {
    guard var markup: PaperMarkup = paperMarkupViewController.markup else { return }
    var subelements: MarkupOrderedSet = markup.subelements
    for element in subelements {
        guard var shape = element as? ShapeMarkup else { continue }
        shape.strokeColor = selectedColor
        shape.fillColor = selectedColor.copy(alpha: 0.15)
        subelements.updateOrAppend(shape)
    }
    markup.subelements = subelements
    markup.backgroundColor = selectedColor.copy(alpha: 0.15)
    paperMarkupViewController.markup = markup
}
Add adornments to each panel swift · at 5:53 ↗
import PaperKit

func addPanelAdornments(for page: Page) {
    var adornments: [MarkupAdornment] = []
    for (panelIndex, panel) in page.panels.enumerated() {
        let adornmentID = UUID()
        adornmentPanelMapping[adornmentID] = panelIndex
        let center = CGPoint(x: panel.midX, y: panel.midY)
        let adornment = MarkupAdornment(
            id: adornmentID,
            anchor: .canvas(location: center),
            imageConfiguration: .systemImage("photo.badge.plus"),
            dragRegion: .fixed,
            scalesWithZoom: false
        )
        adornments.append(adornment)
    }
    paperMarkupViewController.adornments = adornments
}
Handle adornment taps swift · at 6:08 ↗
import ImagePlayground
import PaperKit

func paperMarkupViewController(_ paperMarkupViewController: PaperMarkupViewController, didTapAdornmentWithID id: UUID) {
    guard let panelIndex = adornmentPanelMapping[id] else { return }
    activeImageGenerationPanelIndex = panelIndex

    let imagePlaygroundViewController = ImagePlaygroundViewController()
    imagePlaygroundViewController.delegate = self
    present(imagePlaygroundViewController, animated: true)
}
Place the generated image swift · at 6:20 ↗
import ImagePlayground
import PaperKit

func imageViewController(_ imageViewController: ImagePlaygroundViewController, didCreateImageAt imageURL: URL) {
    guard let panelFrame = activeGenerationPanelFrame,
          let paperMarkupViewController = pageViewController.paperViewController,
          var markup = paperMarkupViewController.markup,
          let image = UIImage(contentsOfFile: imageURL.path) else { return }

    let imageMarkup = ImageMarkup(frame: panelFrame, image: image)
    markup.subelements.append(imageMarkup)
    paperMarkupViewController.markup = markup
}

Resources