TechnologiesSwiftUIPencil Interactions

PencilHoverPose struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A value describing the location and distance of an Apple Pencil hovering in

How it works

PencilHoverPose is a value type that captures the geometry of an Apple Pencil as it hovers above the display, before its tip makes contact. It reports where the Pencil is pointing and how far it sits from the glass, giving you the spatial information needed to preview strokes, highlight targets, or adjust a tool under the user's hand. Reach for PencilHoverPose when you want your interface to react to an approaching Pencil rather than waiting for a touch — the system delivers a fresh pose to you on each hover update.

  1. Receive a pose from a hover phase

    A PencilHoverPose doesn't arrive on its own; the system hands it to you inside a hover phase as the Pencil moves over your view. In the example, the .active case of the phase carries the pose, which is bound with if case .active(let pose) = phase so the rest of the closure can read its properties.

  2. Read the tilt with altitude

    The altitude property reports the angle of the Pencil relative to the screen surface, in radians — a value near zero means the Pencil lies almost flat, while a larger angle means it stands more upright. The example forwards pose.altitude into its altitude state so the reading updates as the user changes the Pencil's tilt.

  3. Read the distance with zOffset

    The zOffset property describes how far the Pencil tip is from the display along the perpendicular axis, letting you gauge proximity as the Pencil descends toward the glass. Here pose.zOffset is stored in the zOffset state and shown in points, so the value shrinks as the Pencil nears the surface.

  4. Drive a view from the live pose

    Because PencilHoverPose is a plain value, you can copy its members straight into @State and let SwiftUI re-render. The example writes both pose.altitude and pose.zOffset into state inside the .onPencilHover callback, and the Text views update on every hover update without any extra plumbing.

Try it — Add Text(String(format: "Tip distance class: %@", zOffset < 10 ? "close" : "far")) next to the existing readouts so you can watch the threshold flip as pose.zOffset changes while you raise and lower the Pencil.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

PencilHoverPose.swift
struct PencilHoverPoseDemo: View {
    @State private var altitude: Double = 0
    @State private var zOffset: Double = 0

    var body: some View {
        VStack(spacing: 12) {
            Text("Hover an Apple Pencil")
                .font(.headline)
            Text(String(format: "Altitude: %.2f rad", altitude))
            Text(String(format: "Z offset: %.1f pt", zOffset))
        }
        .padding()
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.blue.opacity(0.1))
        .onPencilHover { phase in
            if case .active(let pose) = phase {
                altitude = pose.altitude
                zOffset = pose.zOffset
            }
        }
    }
}
Live preview
Hover an Apple Pencil
Hover an Apple Pencil
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →