mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-04-18 12:06:46 +08:00
Merge pull request #1484 from Adlai-Holler/AHNoDuplicateActions
[ASControlNode] Deduplicate Target-Action-Events Entries, Fix Exception When Removing Nil Target
This commit is contained in:
@@ -277,16 +277,17 @@ static BOOL _enableHitTestDebug = NO;
|
||||
}
|
||||
|
||||
// Have we seen this target before for this event?
|
||||
NSMutableArray *targetActions = [eventDispatchTable objectForKey:target];
|
||||
NSMutableSet *targetActions = [eventDispatchTable objectForKey:target];
|
||||
if (!targetActions)
|
||||
{
|
||||
// Nope. Create an actions array for it.
|
||||
targetActions = [[NSMutableArray alloc] initWithCapacity:kASControlNodeActionDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries.
|
||||
// Nope. Create an action set for it.
|
||||
targetActions = [[NSMutableSet alloc] initWithCapacity:kASControlNodeActionDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries.
|
||||
[eventDispatchTable setObject:targetActions forKey:target];
|
||||
}
|
||||
|
||||
// Add the action message.
|
||||
// Note that bizarrely enough UIControl (at least according to the docs) supports duplicate target-action pairs for a particular control event, so we replicate that behavior.
|
||||
// UIControl does not support duplicate target-action-events entries, so we replicate that behavior.
|
||||
// See: https://github.com/facebook/AsyncDisplayKit/files/205466/DuplicateActionsTest.playground.zip
|
||||
[targetActions addObject:NSStringFromSelector(action)];
|
||||
});
|
||||
|
||||
@@ -371,7 +372,7 @@ static BOOL _enableHitTestDebug = NO;
|
||||
if (!target)
|
||||
{
|
||||
// Look at every target, removing target-pairs that have action (or all of its actions).
|
||||
for (id aTarget in eventDispatchTable)
|
||||
for (id aTarget in [eventDispatchTable copy])
|
||||
removeActionFromTarget(aTarget, action);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -106,6 +106,76 @@
|
||||
XCTAssert(controller.hits == 1, @"Controller did not receive the action event");
|
||||
}
|
||||
|
||||
- (void)testRemoveWithoutTargetRemovesTargetlessAction {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node removeTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 0, @"Controller did not receive exactly zero action events");
|
||||
}
|
||||
|
||||
- (void)testRemoveWithTarget {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node removeTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 0, @"Controller did not receive exactly zero action events");
|
||||
}
|
||||
|
||||
- (void)testRemoveWithTargetRemovesAction {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node removeTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 0, @"Controller did not receive exactly zero action events");
|
||||
}
|
||||
|
||||
- (void)testRemoveWithoutTargetRemovesTargetedAction {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node removeTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 0, @"Controller did not receive exactly zero action events");
|
||||
}
|
||||
|
||||
- (void)testDuplicateEntriesWithoutTarget {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node addTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 1, @"Controller did not receive exactly one action event");
|
||||
}
|
||||
|
||||
- (void)testDuplicateEntriesWithTarget {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 1, @"Controller did not receive exactly one action event");
|
||||
}
|
||||
|
||||
- (void)testDuplicateEntriesWithAndWithoutTarget {
|
||||
ASActionSenderEventController *controller = [[ASActionSenderEventController alloc] init];
|
||||
ASControlNode *node = [[ASControlNode alloc] init];
|
||||
[node addTarget:controller action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[node addTarget:nil action:ACTION_SENDER_EVENT forControlEvents:EVENT];
|
||||
[controller.view addSubview:node.view];
|
||||
[node sendActionsForControlEvents:EVENT withEvent:nil];
|
||||
XCTAssertEqual(controller.hits, 2, @"Controller did not receive exactly two action events");
|
||||
}
|
||||
|
||||
- (void)testDeeperHierarchyWithoutTarget {
|
||||
ASActionController *controller = [[ASActionController alloc] init];
|
||||
UIView *view = [[UIView alloc] init];
|
||||
|
||||
Reference in New Issue
Block a user