mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-05 20:22:15 +00:00
Properly consider node for responder methods (#1008)
* Properly consider node for responder methods * Add changelog
This commit is contained in:
parent
d28b17c87f
commit
6c487dd26c
@ -14,6 +14,7 @@
|
|||||||
- Optimize layout flattening, particularly reducing retain/release operations. [Adlai Holler](https://github.com/Adlai-Holler)
|
- Optimize layout flattening, particularly reducing retain/release operations. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
- Create a method to transfer strong C-arrays into immutable NSArrays, reducing retain/release traffic. [Adlai Holler](https://github.com/Adlai-Holler)
|
- Create a method to transfer strong C-arrays into immutable NSArrays, reducing retain/release traffic. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
- Remove yoga layout spec, which has been superseded by tighter Yoga integration (`ASDisplayNode+Yoga.h`)
|
- Remove yoga layout spec, which has been superseded by tighter Yoga integration (`ASDisplayNode+Yoga.h`)
|
||||||
|
- Properly consider node for responder methods [Michael Schneider](https://github.com/maicki)
|
||||||
|
|
||||||
## 2.7
|
## 2.7
|
||||||
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)
|
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)
|
||||||
|
@ -154,6 +154,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
ASDisplayNodeCAssertNotNil(c, @"class is required");
|
ASDisplayNodeCAssertNotNil(c, @"class is required");
|
||||||
|
|
||||||
ASDisplayNodeMethodOverrides overrides = ASDisplayNodeMethodOverrideNone;
|
ASDisplayNodeMethodOverrides overrides = ASDisplayNodeMethodOverrideNone;
|
||||||
|
|
||||||
|
// Handling touches
|
||||||
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(touchesBegan:withEvent:))) {
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(touchesBegan:withEvent:))) {
|
||||||
overrides |= ASDisplayNodeMethodOverrideTouchesBegan;
|
overrides |= ASDisplayNodeMethodOverrideTouchesBegan;
|
||||||
}
|
}
|
||||||
@ -166,13 +168,32 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(touchesEnded:withEvent:))) {
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(touchesEnded:withEvent:))) {
|
||||||
overrides |= ASDisplayNodeMethodOverrideTouchesEnded;
|
overrides |= ASDisplayNodeMethodOverrideTouchesEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Responder chain
|
||||||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(canBecomeFirstResponder))) {
|
||||||
|
overrides |= ASDisplayNodeMethodOverrideCanBecomeFirstResponder;
|
||||||
|
}
|
||||||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(becomeFirstResponder))) {
|
||||||
|
overrides |= ASDisplayNodeMethodOverrideBecomeFirstResponder;
|
||||||
|
}
|
||||||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(canResignFirstResponder))) {
|
||||||
|
overrides |= ASDisplayNodeMethodOverrideCanResignFirstResponder;
|
||||||
|
}
|
||||||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(resignFirstResponder))) {
|
||||||
|
overrides |= ASDisplayNodeMethodOverrideResignFirstResponder;
|
||||||
|
}
|
||||||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(isFirstResponder))) {
|
||||||
|
overrides |= ASDisplayNodeMethodOverrideIsFirstResponder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout related methods
|
||||||
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(layoutSpecThatFits:))) {
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(layoutSpecThatFits:))) {
|
||||||
overrides |= ASDisplayNodeMethodOverrideLayoutSpecThatFits;
|
overrides |= ASDisplayNodeMethodOverrideLayoutSpecThatFits;
|
||||||
}
|
}
|
||||||
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateLayoutThatFits:)) ||
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateLayoutThatFits:)) ||
|
||||||
ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateLayoutThatFits:
|
ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateLayoutThatFits:
|
||||||
restrictedToSize:
|
restrictedToSize:
|
||||||
relativeToParentSize:))) {
|
relativeToParentSize:))) {
|
||||||
overrides |= ASDisplayNodeMethodOverrideCalcLayoutThatFits;
|
overrides |= ASDisplayNodeMethodOverrideCalcLayoutThatFits;
|
||||||
}
|
}
|
||||||
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateSizeThatFits:))) {
|
if (ASDisplayNodeSubclassOverridesSelector(c, @selector(calculateSizeThatFits:))) {
|
||||||
|
@ -29,6 +29,20 @@
|
|||||||
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
||||||
#import <AsyncDisplayKit/ASViewController.h>
|
#import <AsyncDisplayKit/ASViewController.h>
|
||||||
|
|
||||||
|
#pragma mark - ASDisplayNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open access to the method overrides struct for ASDisplayView
|
||||||
|
*/
|
||||||
|
@implementation ASDisplayNode (ASDisplayNodeMethodOverrides_ASDisplayView)
|
||||||
|
|
||||||
|
- (ASDisplayNodeMethodOverrides)methodOverrides
|
||||||
|
{
|
||||||
|
return _methodOverrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
#pragma mark - _ASDisplayViewMethodOverrides
|
#pragma mark - _ASDisplayViewMethodOverrides
|
||||||
|
|
||||||
typedef NS_OPTIONS(NSUInteger, _ASDisplayViewMethodOverrides)
|
typedef NS_OPTIONS(NSUInteger, _ASDisplayViewMethodOverrides)
|
||||||
@ -452,25 +466,24 @@ static _ASDisplayViewMethodOverrides GetASDisplayViewMethodOverrides(Class c)
|
|||||||
|
|
||||||
#pragma mark UIResponder Handling
|
#pragma mark UIResponder Handling
|
||||||
|
|
||||||
#define IMPLEMENT_RESPONDER_METHOD(__sel, __methodOverride) \
|
#define IMPLEMENT_RESPONDER_METHOD(__sel, __nodeMethodOverride, __viewMethodOverride) \
|
||||||
- (BOOL)__sel\
|
- (BOOL)__sel\
|
||||||
{\
|
{\
|
||||||
ASDisplayNode *node = _asyncdisplaykit_node; /* Create strong reference to weak ivar. */ \
|
ASDisplayNode *node = _asyncdisplaykit_node; /* Create strong reference to weak ivar. */ \
|
||||||
SEL sel = @selector(__sel); \
|
/* Check if we can call through to ASDisplayNode subclass directly */ \
|
||||||
/* Prevent an infinite loop in here if [super canBecomeFirstResponder] was called on a
|
if (node.methodOverrides & __nodeMethodOverride) { \
|
||||||
/ _ASDisplayView subclass */ \
|
return [node __sel]; \
|
||||||
if (self->_methodOverrides & __methodOverride) { \
|
|
||||||
/* Check if we can call through to ASDisplayNode subclass directly */ \
|
|
||||||
if (ASDisplayNodeSubclassOverridesSelector([node class], sel)) { \
|
|
||||||
return [node __sel]; \
|
|
||||||
} else { \
|
|
||||||
/* Call through to views superclass as we expect super was called from the
|
|
||||||
_ASDisplayView subclass and a node subclass does not overwrite canBecomeFirstResponder */ \
|
|
||||||
return [self __##__sel]; \
|
|
||||||
} \
|
|
||||||
} else { \
|
} else { \
|
||||||
/* Call through to internal node __canBecomeFirstResponder that will consider the view in responding */ \
|
/* Prevent an infinite loop in here if [super __sel] was called on a \
|
||||||
return [node __##__sel]; \
|
/ _ASDisplayView subclass */ \
|
||||||
|
if (self->_methodOverrides & __viewMethodOverride) { \
|
||||||
|
/* Call through to views superclass as we expect super was called from the
|
||||||
|
_ASDisplayView subclass and a node subclass does not overwrite __sel */ \
|
||||||
|
return [self __##__sel]; \
|
||||||
|
} else { \
|
||||||
|
/* Call through to internal node __sel method that will consider the view in responding */ \
|
||||||
|
return [node __##__sel]; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
}\
|
}\
|
||||||
/* All __ prefixed methods are called from ASDisplayNode to let the view decide in what UIResponder state they \
|
/* All __ prefixed methods are called from ASDisplayNode to let the view decide in what UIResponder state they \
|
||||||
@ -480,11 +493,21 @@ are not overridden by a ASDisplayNode subclass */ \
|
|||||||
return [super __sel]; \
|
return [super __sel]; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
IMPLEMENT_RESPONDER_METHOD(canBecomeFirstResponder, _ASDisplayViewMethodOverrideCanBecomeFirstResponder);
|
IMPLEMENT_RESPONDER_METHOD(canBecomeFirstResponder,
|
||||||
IMPLEMENT_RESPONDER_METHOD(becomeFirstResponder, _ASDisplayViewMethodOverrideBecomeFirstResponder);
|
ASDisplayNodeMethodOverrideCanBecomeFirstResponder,
|
||||||
IMPLEMENT_RESPONDER_METHOD(canResignFirstResponder, _ASDisplayViewMethodOverrideCanResignFirstResponder);
|
_ASDisplayViewMethodOverrideCanBecomeFirstResponder);
|
||||||
IMPLEMENT_RESPONDER_METHOD(resignFirstResponder, _ASDisplayViewMethodOverrideResignFirstResponder);
|
IMPLEMENT_RESPONDER_METHOD(becomeFirstResponder,
|
||||||
IMPLEMENT_RESPONDER_METHOD(isFirstResponder, _ASDisplayViewMethodOverrideIsFirstResponder);
|
ASDisplayNodeMethodOverrideBecomeFirstResponder,
|
||||||
|
_ASDisplayViewMethodOverrideBecomeFirstResponder);
|
||||||
|
IMPLEMENT_RESPONDER_METHOD(canResignFirstResponder,
|
||||||
|
ASDisplayNodeMethodOverrideCanResignFirstResponder,
|
||||||
|
_ASDisplayViewMethodOverrideCanResignFirstResponder);
|
||||||
|
IMPLEMENT_RESPONDER_METHOD(resignFirstResponder,
|
||||||
|
ASDisplayNodeMethodOverrideResignFirstResponder,
|
||||||
|
_ASDisplayViewMethodOverrideResignFirstResponder);
|
||||||
|
IMPLEMENT_RESPONDER_METHOD(isFirstResponder,
|
||||||
|
ASDisplayNodeMethodOverrideIsFirstResponder,
|
||||||
|
_ASDisplayViewMethodOverrideIsFirstResponder);
|
||||||
|
|
||||||
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
||||||
{
|
{
|
||||||
|
@ -44,14 +44,19 @@ _ASPendingState * ASDisplayNodeGetPendingState(ASDisplayNode * node);
|
|||||||
|
|
||||||
typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides)
|
typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides)
|
||||||
{
|
{
|
||||||
ASDisplayNodeMethodOverrideNone = 0,
|
ASDisplayNodeMethodOverrideNone = 0,
|
||||||
ASDisplayNodeMethodOverrideTouchesBegan = 1 << 0,
|
ASDisplayNodeMethodOverrideTouchesBegan = 1 << 0,
|
||||||
ASDisplayNodeMethodOverrideTouchesCancelled = 1 << 1,
|
ASDisplayNodeMethodOverrideTouchesCancelled = 1 << 1,
|
||||||
ASDisplayNodeMethodOverrideTouchesEnded = 1 << 2,
|
ASDisplayNodeMethodOverrideTouchesEnded = 1 << 2,
|
||||||
ASDisplayNodeMethodOverrideTouchesMoved = 1 << 3,
|
ASDisplayNodeMethodOverrideTouchesMoved = 1 << 3,
|
||||||
ASDisplayNodeMethodOverrideLayoutSpecThatFits = 1 << 4,
|
ASDisplayNodeMethodOverrideLayoutSpecThatFits = 1 << 4,
|
||||||
ASDisplayNodeMethodOverrideCalcLayoutThatFits = 1 << 5,
|
ASDisplayNodeMethodOverrideCalcLayoutThatFits = 1 << 5,
|
||||||
ASDisplayNodeMethodOverrideCalcSizeThatFits = 1 << 6,
|
ASDisplayNodeMethodOverrideCalcSizeThatFits = 1 << 6,
|
||||||
|
ASDisplayNodeMethodOverrideCanBecomeFirstResponder= 1 << 7,
|
||||||
|
ASDisplayNodeMethodOverrideBecomeFirstResponder = 1 << 8,
|
||||||
|
ASDisplayNodeMethodOverrideCanResignFirstResponder= 1 << 9,
|
||||||
|
ASDisplayNodeMethodOverrideResignFirstResponder = 1 << 10,
|
||||||
|
ASDisplayNodeMethodOverrideIsFirstResponder = 1 << 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NS_OPTIONS(uint_least32_t, ASDisplayNodeAtomicFlags)
|
typedef NS_OPTIONS(uint_least32_t, ASDisplayNodeAtomicFlags)
|
||||||
|
@ -263,6 +263,14 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface ASTestResponderNodeWithOverride : ASDisplayNode
|
||||||
|
@end
|
||||||
|
@implementation ASTestResponderNodeWithOverride
|
||||||
|
- (BOOL)canBecomeFirstResponder {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
@interface ASTestViewController: ASViewController<ASDisplayNode *>
|
@interface ASTestViewController: ASViewController<ASDisplayNode *>
|
||||||
@end
|
@end
|
||||||
@implementation ASTestViewController
|
@implementation ASTestViewController
|
||||||
@ -353,6 +361,21 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
|||||||
XCTAssertFalse([textNode.view isFirstResponder]);
|
XCTAssertFalse([textNode.view isFirstResponder]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testResponderOverrrideCanBecomeFirstResponder
|
||||||
|
{
|
||||||
|
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||||
|
ASTestResponderNodeWithOverride *node = [[ASTestResponderNodeWithOverride alloc] init];
|
||||||
|
|
||||||
|
// We have to add the text node to a window otherwise the responder methods responses are undefined
|
||||||
|
// This will also create the backing view of the node
|
||||||
|
[window addSubnode:node];
|
||||||
|
[window makeKeyAndVisible];
|
||||||
|
|
||||||
|
XCTAssertTrue([node canBecomeFirstResponder]);
|
||||||
|
XCTAssertTrue([node becomeFirstResponder]);
|
||||||
|
XCTAssertTrue([window firstResponder] == node.view);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testUnsupportedResponderSetupWillThrow
|
- (void)testUnsupportedResponderSetupWillThrow
|
||||||
{
|
{
|
||||||
ASTestResponderNode *node = [[ASTestResponderNode alloc] init];
|
ASTestResponderNode *node = [[ASTestResponderNode alloc] init];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user