Skip to content

Commit

Permalink
Store last component class name on view
Browse files Browse the repository at this point in the history
Summary: Only happens when assertions are enabled - should help debug the task assigned.

Reviewed By: aCorrado

Differential Revision: D20067626

fbshipit-source-id: 3b51e7f22de37fa0976aea36401e7eb7c77607ec
  • Loading branch information
cuva authored and facebook-github-bot committed Feb 25, 2020
1 parent 6a7ea18 commit ca12eff
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 2 deletions.
6 changes: 5 additions & 1 deletion ComponentKit/Core/Action/CKComponentDelegateForwarder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation
CKComponent *responder = CKMountedComponentForView(_view);
id target = [responder targetForAction:selector withSender:responder];
if (!target) {
CKFailAssert(@"Delegate method is being called on an unmounted component's view: %@ selector:%@", _view, NSStringFromSelector(selector));
CKFailAssertWithCategory(
CKLastMountedComponentClassNameForView(_view),
@"Delegate method is being called on an unmounted component's view: %@ selector:%@",
_view,
NSStringFromSelector(selector));
return;
}
[anInvocation invokeWithTarget:target];
Expand Down
2 changes: 2 additions & 0 deletions ComponentKit/Core/CKComponent+UIView.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
#endif

NSString *CKLastMountedComponentClassNameForView(UIView *view);

/** Strong reference back to the associated component while the component is mounted. */
CKComponent *CKMountedComponentForView(UIView *view);

Expand Down
22 changes: 21 additions & 1 deletion ComponentKit/Core/CKComponent+UIView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,22 @@
#import "CKComponent+UIView.h"

#import <ComponentKit/CKMountedObjectForView.h>
#import <ComponentKit/CKComponent.h>
#import <RenderCore/CKAssociatedObject.h>

#import "CKComponent.h"
#if CK_ASSERTIONS_ENABLED
static const void *kMountedComponentClassNameKey = nullptr;
#endif

/** Strong reference back to the associated component while the component is mounted. */
NSString *CKLastMountedComponentClassNameForView(UIView *view)
{
#if CK_ASSERTIONS_ENABLED
return CKGetAssociatedObject_MainThreadAffined(view, &kMountedComponentClassNameKey);
#else
return nil;
#endif
}

/** Strong reference back to the associated component while the component is mounted. */
CKComponent *CKMountedComponentForView(UIView *view)
Expand All @@ -24,4 +38,10 @@
void CKSetMountedComponentForView(UIView *view, CKComponent *component)
{
CKSetMountedObjectForView(view, component);
#if CK_ASSERTIONS_ENABLED
if (component != nil) {
// We want to know which component was last mounted - do not clean this up.
CKSetAssociatedObject_MainThreadAffined(view, &kMountedComponentClassNameKey, component.className);
}
#endif
}
3 changes: 3 additions & 0 deletions ComponentKitTests/CKComponentGestureActionsTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ - (void)testThatTappingAViewSendsComponentAction
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
id mockComponent = [OCMockObject mockForClass:[CKComponent class]];
[[[mockComponent stub] andReturn:@"MyClass"] className];
CKFakeActionComponent *fakeParentComponent = [CKFakeActionComponent new];
[[[mockComponent stub] andReturn:fakeParentComponent] nextResponder];
[[[mockComponent stub] andReturn:fakeParentComponent] targetForAction:[OCMArg anySelector] withSender:[OCMArg any]];
Expand Down Expand Up @@ -106,6 +107,7 @@ - (void)testThatWhenDelegateActionsAreSetTheyProxyToComponent

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
id mockComponent = [OCMockObject mockForClass:[CKComponent class]];
[[[mockComponent stub] andReturn:@"MyClass"] className];
CKFakeActionComponent *fakeParentComponent = [CKFakeActionComponent new];
[[[mockComponent stub] andReturn:fakeParentComponent] nextResponder];
[[[mockComponent stub] andReturn:fakeParentComponent] targetForAction:[OCMArg anySelector] withSender:[OCMArg any]];
Expand All @@ -126,6 +128,7 @@ - (void)testThatWithNoDelegateActionsNoDelegateIsSet
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
id mockComponent = [OCMockObject mockForClass:[CKComponent class]];
[[[mockComponent stub] andReturn:@"MyClass"] className];
CKFakeActionComponent *fakeParentComponent = [CKFakeActionComponent new];
[[[mockComponent stub] andReturn:fakeParentComponent] nextResponder];
[[[mockComponent stub] andReturn:fakeParentComponent] targetForAction:[OCMArg anySelector] withSender:[OCMArg any]];
Expand Down

0 comments on commit ca12eff

Please sign in to comment.