Reputation:
WWDC 2015 - Session 233 - iOS: https://developer.apple.com/videos/play/wwdc2015/233/?time=74
I can find Apple demo code, but for the life of me can't find any actual documentation on [UIEvent predictedTouchesForTouch:]
.
It was supposed to be an iOS 9 API. Is this API active and just not documented yet? I can see the API diff that they added it to Swift, yet still no documentation.
Upvotes: 1
Views: 335
Reputation: 438047
Yes, the documentation for predicted touches (much like the documentation for coalesced touches) is meager. At this point (Xcode 7.2 and 7.3 Beta 4), the only reference I see (outside the WWDC video you reference and other demonstrations scattered about the web) is in the header, which describes the predicted touches as so:
An array of auxiliary
UITouch
’s for touch events that are predicted to occur for a given main touch. These predictions may not exactly match the real behavior of the touch as it moves, so they should be interpreted as an estimate.
But it works precisely as described in the WWDC video you reference, both Swift and Objective-C.
Note, you might not see predicted and coalesced touches on the simulator, but you will if you use a capable device. I see the occasional predicted touch when using my iPhone 6+, but see them consistently on iPad Pro (and even more if you use an Apple Pencil on iPad Pro).
Just to illustrate coalesced and predicted touches, here is an Objective-C demonstration:
@interface ViewController ()
@property (nonatomic, strong) UIBezierPath *path;
@property (nonatomic, weak) CAShapeLayer *pathLayer;
@property (nonatomic, weak) CAShapeLayer *predictedPathLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set up layer for the main (non-predicted) path; line blue line
CAShapeLayer *mainPathLayer = [CAShapeLayer layer];
mainPathLayer.lineWidth = 1;
mainPathLayer.strokeColor = [UIColor blueColor].CGColor;
mainPathLayer.fillColor = [UIColor clearColor].CGColor;
mainPathLayer.lineCap = kCALineCapRound;
mainPathLayer.lineJoin = kCALineJoinRound;
mainPathLayer.frame = self.view.layer.bounds;
[self.view.layer addSublayer:mainPathLayer];
self.pathLayer = mainPathLayer;
// set up layer for the predicted path, if any; thicker red line (just so I can see it clearly)
CAShapeLayer *predictedPathLayer = [CAShapeLayer layer];
predictedPathLayer.lineWidth = 5;
predictedPathLayer.strokeColor = [UIColor redColor].CGColor;
predictedPathLayer.fillColor = [UIColor clearColor].CGColor;
predictedPathLayer.lineCap = kCALineCapRound;
predictedPathLayer.lineJoin = kCALineJoinRound;
predictedPathLayer.frame = self.view.layer.bounds;
[self.view.layer addSublayer:predictedPathLayer];
self.predictedPathLayer = predictedPathLayer;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
self.path = [UIBezierPath bezierPath];
[self.path moveToPoint:[touch locationInView:self.view]];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
// handle coalesced touches
NSArray<UITouch *> *coalescedTouches = [event coalescedTouchesForTouch:touch];
for (UITouch *coalescedTouch in coalescedTouches) {
location = [coalescedTouch locationInView:self.view];
[self.path addLineToPoint:location];
}
self.pathLayer.path = self.path.CGPath;
// now handle predicted touches
UIBezierPath *predictedPath = [UIBezierPath bezierPath];
[predictedPath moveToPoint:location];
NSArray<UITouch *> *predictedTouches = [event predictedTouchesForTouch:touch];
for (UITouch *predictedTouch in predictedTouches) {
[predictedPath addLineToPoint:[predictedTouch locationInView:self.view]];
}
self.predictedPathLayer.path = predictedPath.CGPath;
// for diagnostic purposes, let's log the count of each; do not do this in production app
NSLog(@"%ld %ld", [coalescedTouches count], [predictedTouches count]);
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.predictedPathLayer.path = NULL; // discard any predicted path, because that's no longer valid
}
@end
If you need to support iOS versions before 9, you'll want to check respondsToSelector
, too.
The Swift example is very similar. See this unrelated post about smooth curves, which illustrates how to use predicted (and coalesced) touches in Swift: Drawing class drawing straight lines instead of curved lines
Upvotes: 2