I understand that this response clearly states that this is not possible without a private function call. Therefore, according to Apple's terms, this approach cannot be used on an App Store app.
However, some apps already seem to use this function call:
- Penultimate for actual palm rejection without a predefined rejection area like in Note Taker HD
- Virtuoso for pressure sensitivity, which they call "TrueVelocity 2"
- GarageBand also for pressure sensitivity
Clearly, this approach is already widely used in App Store apps despite Apple's restrictions.
tl;dr What is the private function call on iOS to get touch size?
Size and pressure are two different animals. Penultimate most likely tests for a large amount of touches in a certain area (palms have a large area after all, generate tons of touches).
Touch "size" does not exist. IOS touch events are generated when a finger contacts the screen. The OS then takes a center point from the touch and that's what you get. It's not a CGRect, it's a CGPoint.
Pressure is 'easier' though. see here for a workaround: Tap pressure strength detection using accelerometer
And while I see you're in the market for private API's, github hosts a number of class dumps: http://github.com/kennytm/iphone-private-frameworks and https://github.com/nst/iOS-Runtime-Headers
With iOS8, you can access the touch.majorRadius
property, which is a CGFloat
, grows in multiples of 10.45 and is proportional to the radius of the touched area in Millimeters. touch.majorRadiusTolerance is the second property which can be used with iOS8 and gives the accuracy of the touch radius information. In my measurements it was always half of the majorRadius
step size.
On the iPad Pro the touchscreen is three times more sensitive and picks up the weak signal from the Apple pencil which is below the reporting threshold on older iPad models. The touch radius of the Pencil is reported as 0.25, while even the slightest finger contact will report as 20.84 or more.
Use it like this within your UIView method:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Regular multitouch handling.
[super touchesBegan:touches withEvent:event];
CGPoint center = [touch locationInView:self];
NSLog(@"Touch detected at %6.1f | %6.1f", center.x, center.y);
CGFloat radius = [touch majorRadius];
NSLog(@"Radius = %5.1f; lower limit = %5.1f; upper limit = %5.1f", radius, radius-touch.majorRadiusTolerance, radius+touch.majorRadiusTolerance);
}
If you're interested in the private (i.e., don't submit this to the app store method, you're looking for -
@interface UITouch (Private)
-(float)_pathMajorRadius;
@end
In my (private!) use of this, 10
was a good threshold for determining when a person was using their finger/stylus or resting their hand on the device.
Hope this is helpful to someone. Again, don't use this in the App Store.
FYI looks like iOS 8 introduced a couple properties for estimating the radius of a UITouch
: majorRadius
and majorRadiusTolerance
.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITouch_Class/index.html