I figured this one out, yet thought it worthy of its own question answer pair.
I'm new to Xcode and Objective C, and getting to know its varied eccentricities. For instance, the compiler warning "warning: ''may not respond to '<[-|+]FUNCTION>'" appears when I try to compile the following code, which all appears in my implementation file since I desire to create a private static utility function for this class:
// Here's the function declaration in the implementation file (I don't want it in the header)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
...
// Later on, here's a call to that same function:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
...
When compiled, this produces the warning above. Next, I'll post my resolution. Feel free to contribute your ideas as well!
If what you really want is a private method, that is, you don't want the method to be in the header file, then I like to use a Category to accomplish this. I just define the category above my implementation.
// Enforce private methods by putting them in a category.
#interface YourClass (PrivateMethods)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse;
#end
#implementation YourClass
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
#end
Now, it doesn't matter what the order of your methods in your implementation is which is nice so you can properly "#pragma mark"
The problem is with your method call:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
Note that the first 'r' in "authenticationredirectTo:..." is lower case, but you've declared it as "authenticationRedirectTo:...", with a capital 'R'. Given that, it's no surprise that the compiler complains that it can't find a declaration for the method you're calling. The code will likely crash on that line, too, since the method with the lower-case 'r' isn't defined.
What i think the problem is, you are declaring the function after the call to this function. And while compiling it just could not find it.
OK, here's my solution as promised:
Problem 1: Xcode will generate erroneous warnings when a function declaration or implementation appears after the call in processed source code. In my case, they are in the same file so I was able to move to function implementation above the call.
Also check the order of your imports to ensure such a function is imported before an import that calls it. I didn't see this but saw other posts where this was the case.
Problem 2: It seems Xcode has some limitations on the LENGTH of function names. Shortening my function name as shown in the snip below resolved the issue. I'll obviously pick something more meaningful.
// Here is the warning function commented out and a *shorter* name in place.
//+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
+(void)X:(NSURL *)url Y:(NSString *)relayState Z:(NSString *)samlResponse {
Hope this helps you with your troubles. Don't forget to vote this answer if it is useful.
Related
I hope my question is not too basic, as I am new to both obj-c and OCMockito!
I have a void method that I want to stub, so that it does not perform its actions when running a test.
My Method:
-(void)myVoidMethod
{ .. }
I would like to stub it in a way similar to this:
[given([mockDataManager saveChangesToCoreData])];
However if I dont specify a "willReturn" statement I get the following error:
"Argument type 'void' is incomplete"
How can I achieve this in OCMockito?
After getting more details from comments I decide to write the answer here.
IMO partial stubbing (spies) are bad practise. I used it two times in really big legacy project and I would like to change that to something cleaner at some point.
The same opinion is shared between other people. As quick solution you could follow advice from here - subclass and override the method.
Declaring dummy protocol where this method declared as returning id will fix compile error.
#protocol _dummyProtocol
- (id)methodThatReallyReturnVoid;
#end
[[(id<_dummyProtocol>)[mockObject stub] methodThatReallyReturnVoid] andDo:^(NSInvocation *inv){}];
Does it matter if I define a function with one argument name in the .h file, for example...
-(foo *) initWithId:(NSString *)id;
And then in my implementation give the argument a different name because it hides a class property:
-(foo *) initWithID:(NSString *)idString;
I know that the autocomplete files use .h as the 'basis' for their autocomplete fillers, and while it doesn't apply to this scenario, I prefer to use the property name in my functions to remain as consistent in my coding style as possible. It makes more sense to understand that getFoo and setFoo both apply to the same property 'foo' as in -(bar *) initWithFoo:(id) foo;.
As far as I can tell, the compiler doesn't have any issues with it, but somehow it seems like it SHOULD matter.
The LLVM analyzer in Xcode does seem to care about some things like methods starting with new and copy.
Here's a sample warning when I name a property starting with new:
"Property's synthesized getter follows Cocoa naming convention for
returning 'owned' objects"
(the #property had a #synthesize that created a getter method starting with new).
No, the compiler doesn't care. Other people who read your code might care.
the only time it really matters is if you have an instance variable name with the same name.
#synthesize something;
- (void)methodForSomething:(id)something
{
something = something;
}
this will throw an error. obviously the solution is to modify your instance variables naming.
#synthesize something = _something;
other then that, parameter names dont matter.
I have a class that has two classes A and B added to it. In a method in class A, I am trying to call a class B method
Let's assume that the parent class is debugZoneScene, debugZoneLayer is class A and tetraCounter is class B.
Here is a method from debugZoneLayer (class A):
-(void) getHeroVel {
DebugZoneScene *debugZoneScene = (DebugZoneScene*)self.parent;
[debugZoneScene.tetraCounter setTetras];
}
It calls the method, but I get the warning:
'-[DebugZoneLayer getHeroVel]':
'CCNode' may not respond to '-setTetras' (Messages without a matching method signature will be assumed to return 'id' and accept '...' as arguments.)
I've tried Googling this, but I couldn't really find anything that related exactly to my problem. I am using Cocos2D, but I think this problem doesn't have anything to do directly with that, and can still be resolved having knowledge in Objective C. Any ideas?
The compiler is telling you that it thinks that debugZoneScene.tetraCounter is an object of type CCNode, not whatever your ClassB is. Check how tetraCounter is declared and allocated in DebugZoneScene.
You can make the warning go away by casting:
[(ClassB *)(debugZoneScene.tetraCounter) setTetras];
this tells the compiler that you don't care what it thinks and you're sure that the object is ClassB. This doesn't solve the actual problem, however.
Your pseudo really fits you... without more details about the signature of setTetras, it will be quite difficult to guess what is wrong in your code ^^
Anyway did you #import the header for TatraCounter class declaration, so that the file where you wrote this code knows about the methods available (and their signature) for the TetraCounter objects?
I am trying to implement a private method which takes an NSMutableDictionary and a Player object as its parameters. As it is a private method, the only place that it exists is in the ".m" file.
It is declared as
-(void) incrementScore: (NSMutableDictionary*) scoreboard forPlayer: ( Player* ) player {
and I call it as follows :
[ self incrementScore:deuceScore forPlayer:p];
However,it won't compile - I get
may not response to message -incrementScore:forplayer
I'm not sure where my error lies - do I need to declare the method in the ".h" file, or elsewhere in the ".m" file, or have I just got the syntax completely wrong?
The compiler needs to find a declaration for your method somewhere before you use it. This be done in three way:
Declare the method in the (public) #interface for the class in its .h file .
Declare the method in a class extension (a semi-private #interface, usually at the top of the .m files).
Define the method somewhere in the #implementation before your first use of it.
This is only a warning not a compile error... (if you changed preferences to treat all warnings like error it'll be a compile error).
Probably the line calling the method is above (in the .m file) the declaration method. Move the method just below #implementation directive, or above the method with the calling line. The warning/error should disapper.
The Compiler claims an error saying: "initializer element is not constant", when I try to initialize a static variable inside a method with a call to a static method (with + in its definition).
Anyway I can tell him that this method always returns the same value. I know this is not the same as static method, but there seems to be no constant methods in Objective-C (other than macros which won't work here because I am calling UI_USER_INTERFACE_IDIOM() from inside the method).
There's actually another solution in addition to Yuji's. You can create a function and prefix it with a GCC attribute (also works in Clang and LLVM) that will cause it to be executed before main() is. I've used this approach several times, and it looks something like this:
static NSString *foo;
__attribute__((constructor)) initializeFoo() {
foo = ...;
}
When you actually use foo, it will already be initialized. This mean you don't have to check whether it's nil each time. (This is certainly a minor performance benefit, though multiplied by the number of times you use it, but it can also simplify one or more other regions of code. For example, if you reference the static variable in N different places, you might have to check for nil in all N or risk a crash. Often, people call a function or use a #define to handle initialization, and if that code is only actually used once, it can be a penalty worth removing.
You cannot do that in Objective-C.
There are two solutions:
Switch to Objective-C++. Change the file extension from .m to .mm.
Initialize it with nil, and check it when you first use it, as in:
static NSString*foo=nil;
if(!foo){
foo=[ ... ] ;
}