- (void)doIt
{
[_foo bar];
// produces compile time error: "No visible @interface for 'FooClass'
// declares the selector 'bar'"
}
In the earlier days of Objective-C, when I called a method that the compiler doesn't know about, I would just get a warning. Then, something like a year ago, the compiler changed and such things are now an error. Does anybody know when this happened (__weak
?)
What I did to solve the problem
There are a few methods that I know which can solve the problem, somehow. However, I hope there is an easier way.
A) declare an interface
@interface FooClass (MichaelHacksIt)
- (void) bar;
@end
// ...
- (void) doIt
{
[_foo bar];
}
B) use -performSelector:
- (void)doIt
{
[_foo performSelector:@selector(bar)];
}
C)
Because solution B sometimes produces an 'Undeclared selector' warning, and because we don't want Apple to know which methods we are calling, at all times, there is a third solution:
- (void)doIt
{
SEL bar_sel = NSSelectorFromString(@"bar");
[_foo performSelector:bar_sel];
}
D)
If the arguments to the method call are not just objects, we need to use NSInvocation
instead. That's really ugly.
What I would like to do
Is there maybe some compiler switch that disables the error? Under the hood, a message send is always just a call to objc_msgSend()
, and linking to the method implementation is done at runtime. So, disabling the error should in principle be possible. What I would like to do is something similar to:
- (void)doIt
{
#pragma clang diagnostic push
#pragma clang error disable objc_method_unknown_error
[_foo bar];
#pragma clang diagnostic pop
}
Is there such a compile time switch? Is there maybe a compiler flag that can be passed at the command line that produces this behaviour?
Why I am asking
These questions arise when you try to use undocumented methods. For example to change the status bar text color in iOS. Or to override some undocumented method in a subclass when you have the source, but you don't want to modify it for some reason.
Does my solution A have any effect at runtime? Is it possible somehow to see in the binary that I declared a private category (MichaelHacksIt
) or does it just silence the compiler? (Note that there is no @implementation
for this category.)
My main question is: Is it possible to disable the "No visible @interface for 'SomeClass' declares the selector 'fooBar'"?