From 7b86303f206c4fcaf91385c4cad9f8c4d1596b2e Mon Sep 17 00:00:00 2001 From: Ryan Nystrom Date: Tue, 6 Jan 2015 14:06:40 -0800 Subject: [PATCH] Forward touch events to either the node or super `_ASDisplayView` now forwards touch events to either super or it's node, depending on whether or not the node implements the methods. fixes #199 --- AsyncDisplayKit/ASDisplayNode.mm | 51 +++++++------------ AsyncDisplayKit/Details/_ASDisplayView.mm | 28 +++++++--- .../Private/ASDisplayNodeInternal.h | 11 ++++ 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 0a0d5732ae..ac83664fad 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -118,6 +118,21 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) _flags.implementsDrawParameters = ([self respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0); _fadeAnimationDuration = 0.1; + + ASDisplayNodeMethodOverrides overrides = ASDisplayNodeMethodOverrideNone; + if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(touchesBegan:withEvent:))) { + overrides |= ASDisplayNodeMethodOverrideTouchesBegan; + } + if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(touchesMoved:withEvent:))) { + overrides |= ASDisplayNodeMethodOverrideTouchesMoved; + } + if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(touchesCancelled:withEvent:))) { + overrides |= ASDisplayNodeMethodOverrideTouchesCancelled; + } + if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(touchesEnded:withEvent:))) { + overrides |= ASDisplayNodeMethodOverrideTouchesEnded; + } + _methodOverrides = overrides; } - (id)init @@ -1303,50 +1318,22 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - ASDisplayNodeAssertMainThread(); - - if (!_view) - return; - - // If we reach the base implementation, forward up the view hierarchy. - UIView *superview = _view.superview; - [superview touchesBegan:touches withEvent:event]; + // subclass hook } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - ASDisplayNodeAssertMainThread(); - - if (!_view) - return; - - // If we reach the base implementation, forward up the view hierarchy. - UIView *superview = _view.superview; - [superview touchesMoved:touches withEvent:event]; + // subclass hook } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - ASDisplayNodeAssertMainThread(); - - if (!_view) - return; - - // If we reach the base implementation, forward up the view hierarchy. - UIView *superview = _view.superview; - [superview touchesEnded:touches withEvent:event]; + // subclass hook } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - ASDisplayNodeAssertMainThread(); - - if (!_view) - return; - - // If we reach the base implementation, forward up the view hierarchy. - UIView *superview = _view.superview; - [superview touchesCancelled:touches withEvent:event]; + // subclass hook } - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer diff --git a/AsyncDisplayKit/Details/_ASDisplayView.mm b/AsyncDisplayKit/Details/_ASDisplayView.mm index 4c97df8853..f5bdb7b9ed 100644 --- a/AsyncDisplayKit/Details/_ASDisplayView.mm +++ b/AsyncDisplayKit/Details/_ASDisplayView.mm @@ -151,26 +151,38 @@ #pragma mark - Event Handling + UIResponder Overrides - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - [super touchesBegan:touches withEvent:event]; - [_node touchesBegan:touches withEvent:event]; + if (_node.methodOverrides & ASDisplayNodeMethodOverrideTouchesBegan) { + [_node touchesBegan:touches withEvent:event]; + } else { + [super touchesBegan:touches withEvent:event]; + } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - [super touchesMoved:touches withEvent:event]; - [_node touchesMoved:touches withEvent:event]; + if (_node.methodOverrides & ASDisplayNodeMethodOverrideTouchesMoved) { + [_node touchesMoved:touches withEvent:event]; + } else { + [super touchesMoved:touches withEvent:event]; + } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [super touchesEnded:touches withEvent:event]; - [_node touchesEnded:touches withEvent:event]; + if (_node.methodOverrides & ASDisplayNodeMethodOverrideTouchesEnded) { + [_node touchesEnded:touches withEvent:event]; + } else { + [super touchesEnded:touches withEvent:event]; + } } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [super touchesCancelled:touches withEvent:event]; - [_node touchesCancelled:touches withEvent:event]; + if (_node.methodOverrides & ASDisplayNodeMethodOverrideTouchesCancelled) { + [_node touchesCancelled:touches withEvent:event]; + } else { + [super touchesCancelled:touches withEvent:event]; + } } - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index 501324e409..8cc6be571a 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -22,6 +22,14 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector); CGFloat ASDisplayNodeScreenScale(); void ASDisplayNodePerformBlockOnMainThread(void (^block)()); +typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) { + ASDisplayNodeMethodOverrideNone = 0, + ASDisplayNodeMethodOverrideTouchesBegan = 1 << 0, + ASDisplayNodeMethodOverrideTouchesCancelled = 1 << 1, + ASDisplayNodeMethodOverrideTouchesEnded = 1 << 2, + ASDisplayNodeMethodOverrideTouchesMoved = 1 << 3 +}; + @class _ASPendingState; // Allow 2^n increments of begin disabling hierarchy notifications @@ -102,6 +110,9 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); // Creates a pendingViewState if one doesn't exist. Allows setting view properties on a bg thread before there is a view. @property (atomic, retain, readonly) _ASPendingState *pendingViewState; +// Bitmask to check which methods an object overrides. +@property (nonatomic, assign, readonly) ASDisplayNodeMethodOverrides methodOverrides; + // Swizzle to extend the builtin functionality with custom logic - (BOOL)__shouldLoadViewOrLayer; - (BOOL)__shouldSize;