diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 17ec215cee..fbb97c53f5 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -432,6 +432,16 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)(); */ - (CGRect)convertRect:(CGRect)rect fromNode:(ASDisplayNode *)node; +/** @name UIResponder methods */ + +// By default these fall through to the underlying view, but can be overridden. +- (BOOL)canBecomeFirstResponder; // default==NO +- (BOOL)becomeFirstResponder; // default==NO (no-op) +- (BOOL)canResignFirstResponder; // default==YES +- (BOOL)resignFirstResponder; // default==NO (no-op) +- (BOOL)isFirstResponder; +- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; + @end @@ -468,15 +478,6 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)(); - (void)setNeedsDisplay; // Marks the view as needing display. Convenience for use whether view is created or not, or from a background thread. - (void)setNeedsLayout; // Marks the view as needing layout. Convenience for use whether view is created or not, or from a background thread. -// UIResponder methods -// By default these fall through to the underlying view, but can be overridden. -- (BOOL)canBecomeFirstResponder; // default==NO -- (BOOL)becomeFirstResponder; // default==NO (no-op) -- (BOOL)canResignFirstResponder; // default==YES -- (BOOL)resignFirstResponder; // default==YES (no-op) -- (BOOL)isFirstResponder; -- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; - @property (atomic, retain) id contents; // default=nil @property (atomic, assign) BOOL clipsToBounds; // default==NO @property (atomic, getter=isOpaque) BOOL opaque; // default==YES diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 10a173d84a..c3cea9454d 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1701,24 +1701,29 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, return NO; } -- (BOOL)becomeFirstResponder { - return [self.view becomeFirstResponder]; -} - - (BOOL)canResignFirstResponder { return YES; } -- (BOOL)resignFirstResponder { - return [self.view resignFirstResponder]; +- (BOOL)isFirstResponder { + ASDisplayNodeAssertMainThread(); + return _view != nil && [_view isFirstResponder]; } -- (BOOL)isFirstResponder { - return [self.view isFirstResponder]; +// Note: this implicitly loads the view if it hasn't been loaded yet. +- (BOOL)becomeFirstResponder { + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self canBecomeFirstResponder] && [self.view becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder { + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self canResignFirstResponder] && [_view resignFirstResponder]; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - return [self.view canPerformAction:action withSender:sender]; + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self.view canPerformAction:action withSender:sender]; } @end