Pass in Actions
Follow this simple rule: Selectors should be implemented in the same file they are referenced.
The following counterexample establishes a hidden coupling between the parent and child component. If another component tries to use ChildComponent
or if the method is renamed in ParentComponent
, it will crash at runtime.
@implementation ParentComponent+ (instancetype)new{return [super newWithComponent:[ChildComponent new]];}- (void)someAction:(CKComponent *)sender{// Do something}@end@implementation ChildComponent+ (instancetype)new{return [super newWithComponent:CK::ButtonComponentBuilder.action(@selector(someAction:)).build()];}@end
Instead, always pass selectors from parents to children. In the following example, it is explicit that the child component needs a CKTypedComponentAction<>
selector. If the parent component renames the someAction:
method, it's far easier to catch renaming the parameter.
@implementation ParentComponent+ (instancetype)new{CKComponentScope scope(self);return [super newWithComponent:[ChildComponentnewWithAction:{scope, @selector(someAction:)}]];}- (void)someAction:(CKComponent *)sender{// Do something}@end@implementation ChildComponent+ (instancetype)newWithAction:(CKTypedComponentAction<>)action{return [super newWithComponent:CK::ButtonComponentBuilder().action(action).build()];}@end