in ComponentKit/Core/Action/CKAction.mm [265:315]
CKComponentViewAttributeValue CKComponentActionAttribute(const CKAction<UIEvent *> action,
UIControlEvents controlEvents) noexcept
{
if (!action) {
return {
{"CKComponentActionAttribute-no-op", ^(UIControl *control, id value) {}, ^(UIControl *control, id value) {}},
// Use a bogus value for the attribute's "value". All the information is encoded in the attribute itself.
@YES
};
}
static ForwarderMap *map = new ForwarderMap(); // access on main thread only; never destructed to avoid static destruction fiasco
return {
{
std::string("CKComponentActionAttribute-") + action.identifier() + "-" + std::to_string(controlEvents),
^(UIControl *control, id value){
CKComponentActionList *list = RCGetAssociatedObject_MainThreadAffined(control, ck_actionListKey);
if (list == nil) {
list = [CKComponentActionList new];
RCSetAssociatedObject_MainThreadAffined(control, ck_actionListKey, list);
}
if (list->_registeredForwarders.insert(controlEvents).second) {
// Since this is the first time we've seen this {control, events} pair, add a Forwarder as a target.
const auto it = map->find(controlEvents);
CKComponentActionControlForwarder *const forwarder =
(it == map->end())
? map->insert({controlEvents, [[CKComponentActionControlForwarder alloc] initWithControlEvents:controlEvents]}).first->second
: it->second;
[control addTarget:forwarder
action:@selector(handleControlEventFromSender:withEvent:)
forControlEvents:controlEvents];
}
list->_actions[controlEvents].push_back(action);
},
^(UIControl *control, id value){
CKComponentActionList *const list = RCGetAssociatedObject_MainThreadAffined(control, ck_actionListKey);
RCCAssertNotNil(list, @"Unapplicator should always find an action list installed by applicator");
auto &actionList = list->_actions[controlEvents];
auto it = CK::find(actionList, action);
if (it == actionList.end()) {
RCCFailAssert(@"Unapplicator should always find item in action list");
return;
}
actionList.erase(it);
// Don't bother unsetting the action list or removing the forwarder as a target; both are harmless.
}
},
// Use a bogus value for the attribute's "value". All the information is encoded in the attribute itself.
@YES
};
}