Finger input interrupted while drawing with Apple Pencil + palm resting on display

I’m investigating an issue with simultaneous Apple Pencil and finger input on iPad.

Apple Pencil + finger input works correctly while the Pencil user’s hand/palm is off the display.

However, when drawing naturally with Apple Pencil with the palm resting on the display, an existing finger drawing contact elsewhere on the screen can be cancelled and then stop receiving input for several seconds. Pencil input continues normally throughout.

Initially I suspected PencilKit, but I’ve reproduced the underlying behaviour below PencilKit/SwiftUI. Instrumenting UIKit at UIApplication.sendEvent shows the finger touch being cancelled and, in some cases, no further events for that finger for ~4–5 seconds while Pencil MOVED events continue to arrive normally.

Everything delivered to the application is accounted for, so this appears to occur before our drawing/rendering code.

Is this expected behaviour from the iPad’s Pencil/palm rejection?

More specifically:

  • Is there any supported way to tell UIKit that an existing finger contact should remain intentional while Pencil + palm contact is present?
  • Is palm rejection configurable at this level?
  • Is there another public input API we should be using for this scenario?

We’re currently testing UIEvent.coalescedTouches(for:) to determine whether additional genuine finger samples are available during these apparent gaps, but haven’t completed that test yet.

Any guidance on whether this interaction is expected to be supportable through public UIKit APIs would be appreciated.

Answered by DTS Engineer in 906681022

Palm rejection has no public API. The word does not occur in any framework header in the iOS 27 SDK. There is nothing to configure at that level, and nothing on UITouch reports that a contact was rejected.

The cancellation itself is documented. UIResponder.h states that a responder "will receive either touchesEnded:withEvent: or touchesCancelled:withEvent: for each touch it is handling", followed by "You must handle cancelled touches to ensure correct behavior in your application." UITouchPhaseCancelled is described as covering the case where "a touch doesn't end but we need to stop tracking", with one example given rather than a list of causes. So cancellation is a contract to handle, and there is no API for marking a contact you already hold as one to keep.

Coalesced touches will not recover the gap. Getting high-fidelity input with coalesced touches (https://developer.apple.com/documentation/uikit/getting-high-fidelity-input-with-coalesced-touches) describes the method as returning "the array of all touches since the last event". It adds: "You must retrieve coalesced touches immediately when handling an event." The mechanism exists because devices report at up to 240 Hz while UIKit delivers at around 60 Hz, so it is attached to an event you are handling. With no finger events delivered for several seconds there is no event to ask, and nothing held for later retrieval.

For tracking the two input types separately, the documented pattern is two gesture recognizers filtered by allowedTouchTypes (https://developer.apple.com/documentation/uikit/uigesturerecognizer/allowedtouchtypes). Leveraging touch input for drawing apps (https://developer.apple.com/documentation/uikit/leveraging-touch-input-for-drawing-apps) does that, one recognizer restricted to .pencil and one to .direct, both with cancelsTouchesInView set to false. Also worth checking in your hierarchy: requiresExclusiveTouchType (https://developer.apple.com/documentation/uikit/uigesturerecognizer/requiresexclusivetouchtype) defaults to YES per its header. When true, "the gesture recognizer automatically ignores new touches whose type doesn't match the type of the initial touch."

That sample also stops tracking finger strokes once Apple Pencil is in use. When it enters pencil mode it removes the finger stroke recognizer from the view outright, and changes the scroll view's pan to a single finger. So while Apple Pencil is drawing, finger contacts pan the canvas rather than drawing on it. It does not carry a finger stroke and an Apple Pencil stroke at the same time. That is what the published sample does, rather than a statement about what the system intends.

Whether the cancellation you are seeing is intended I cannot tell you, and it is not documented either way. Instrumenting sendEvent was the right move, because it establishes that the cancellation arrives before your code, which is the part a report needs. The cancellation is worth filing in Feedback Assistant, with the timing you already have: the four-to-five-second gap, and Apple Pencil MOVED events continuing across it. Feedback Assistant is at https://developer.apple.com/feedback-assistant/

Palm rejection has no public API. The word does not occur in any framework header in the iOS 27 SDK. There is nothing to configure at that level, and nothing on UITouch reports that a contact was rejected.

The cancellation itself is documented. UIResponder.h states that a responder "will receive either touchesEnded:withEvent: or touchesCancelled:withEvent: for each touch it is handling", followed by "You must handle cancelled touches to ensure correct behavior in your application." UITouchPhaseCancelled is described as covering the case where "a touch doesn't end but we need to stop tracking", with one example given rather than a list of causes. So cancellation is a contract to handle, and there is no API for marking a contact you already hold as one to keep.

Coalesced touches will not recover the gap. Getting high-fidelity input with coalesced touches (https://developer.apple.com/documentation/uikit/getting-high-fidelity-input-with-coalesced-touches) describes the method as returning "the array of all touches since the last event". It adds: "You must retrieve coalesced touches immediately when handling an event." The mechanism exists because devices report at up to 240 Hz while UIKit delivers at around 60 Hz, so it is attached to an event you are handling. With no finger events delivered for several seconds there is no event to ask, and nothing held for later retrieval.

For tracking the two input types separately, the documented pattern is two gesture recognizers filtered by allowedTouchTypes (https://developer.apple.com/documentation/uikit/uigesturerecognizer/allowedtouchtypes). Leveraging touch input for drawing apps (https://developer.apple.com/documentation/uikit/leveraging-touch-input-for-drawing-apps) does that, one recognizer restricted to .pencil and one to .direct, both with cancelsTouchesInView set to false. Also worth checking in your hierarchy: requiresExclusiveTouchType (https://developer.apple.com/documentation/uikit/uigesturerecognizer/requiresexclusivetouchtype) defaults to YES per its header. When true, "the gesture recognizer automatically ignores new touches whose type doesn't match the type of the initial touch."

That sample also stops tracking finger strokes once Apple Pencil is in use. When it enters pencil mode it removes the finger stroke recognizer from the view outright, and changes the scroll view's pan to a single finger. So while Apple Pencil is drawing, finger contacts pan the canvas rather than drawing on it. It does not carry a finger stroke and an Apple Pencil stroke at the same time. That is what the published sample does, rather than a statement about what the system intends.

Whether the cancellation you are seeing is intended I cannot tell you, and it is not documented either way. Instrumenting sendEvent was the right move, because it establishes that the cancellation arrives before your code, which is the part a report needs. The cancellation is worth filing in Feedback Assistant, with the timing you already have: the four-to-five-second gap, and Apple Pencil MOVED events continuing across it. Feedback Assistant is at https://developer.apple.com/feedback-assistant/

Finger input interrupted while drawing with Apple Pencil + palm resting on display
 
 
Q