15

I have a parent view controller and a child view controller. In child view controller's view, I have a UIButton called "startButton". To that button, I have added a target as below

[startButton addTarget:[self parentViewController] action:@selector(test:) forControlEvents:UIControlEventTouchUpInside];

I have implemented, test: method in parent controller and this works perfectly fine for me. When the button is tapped, the event is passed from child view controller to parent view controller and code snippets within test: method gets executed.

But my problem is, I am getting a warning message, "Undeclared selector test:". I know, I am getting it because test: is not implemented in child view controller implementation file.

Is there any way to suppress this warning alone? Most of the suggestions I have seen here makes the entire warnings to get suppressed but I want to suppress above mentioned warning alone.

Thanks

slysid
  • 5,236
  • 7
  • 36
  • 59
  • 1
    there should be test method in your parentViewController – Sunny Shah Feb 06 '14 at 09:01
  • possible duplicate of [Dynamic forwarding: suppress Incomplete Implementation warning](http://stackoverflow.com/questions/14444203/dynamic-forwarding-suppress-incomplete-implementation-warning) – Popeye Feb 06 '14 at 09:10
  • @Popeye it's not a duplicate of that question as it's a different warning he wants to suppress. – Ben Clayton Feb 07 '14 at 09:06
  • http://stackoverflow.com/questions/6224976/how-to-get-rid-of-the-undeclared-selector-warning – Hemang Oct 15 '14 at 06:31

6 Answers6

17

If you know for sure that you've done the right thing, and the code actually works fine, you can stop Xcode warning you about it by surrounding the method with #pragma clang preprocessor commands.

For example:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"

[startButton addTarget:[self parentViewController] action:@selector(test:) forControlEvents:UIControlEventTouchUpInside]; 

#pragma clang diagnostic pop

Any 'missing messages' between the push and pop commands will not be reported by Xcode. I suggest having as little code as possible between them to prevent real problems in your code being unreported.

Brad The App Guy
  • 16,255
  • 2
  • 41
  • 60
Ben Clayton
  • 80,996
  • 26
  • 120
  • 129
  • 2
    the above answer did not work for me. Replace #pragma ide diagnostic ignored "UnresolvedMessage" with #pragma clang diagnostic ignored "-Wundeclared-selector" and it works. – Pellet Jul 30 '14 at 09:08
  • Thanks @Pellet. Which version of Xcode are you using? It's possible this answer is now out-of-date – Ben Clayton Jul 31 '14 at 09:08
17

There is no need to suppress the warning if you can avoid it:

Declare the test: method in the @interface (in the .h file) of the parent view controller, and import that .h file in the child view controller's implementation (.m) file.

Then the compiler knows about the method and you don't get a warning about an undeclared selector anymore.

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
1

Following code will make this warning as disappear( dynamic create selector). But it will crash in runtime if undeclared in parentviewcontroller.

[startButton addTarget:[self parentViewController] action:NSSelectorFromString(@"test:") forControlEvents:UIControlEventTouchUpInside];
Mani
  • 17,549
  • 13
  • 79
  • 100
0

You can always implement test: in the child view controller, and do the following:

- (void)test:(Parameters)param {
      [self.parentViewController test:param];
}

The edit the target to self instead of [self parentViewController]

Lord Zsolt
  • 6,492
  • 9
  • 46
  • 76
0

Another option is to declare it within a protocol (within the same file as selector usage or a header it includes):

@protocol DummyProtocolToForwardDeclareSelector
-(void)test:(BOOL)testArgument;
@end

This will suppress the warnings only for this particular selector but you could add others to the same protocol.

Joseph Lord
  • 6,446
  • 1
  • 28
  • 32
0

Yet another and possibly more correct option is to extend the interface of the class that has the method targeted by the selector.

@interface ClassThatHasTargetOfSelector ()
-(void)test:(BOOL)testArgument;
@end
Josh G
  • 1