diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 0a0d5732..ac83664f 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 4c97df88..f5bdb7b9 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 501324e4..8cc6be57 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;