Redundant Compiler Warnings - objective-c

I have found that very often, when calling myMethod asoociated with myObject1 from myObject2, I get the warning that "myObject1 may not respond to -myMethod", but then the program runs just fine anyway. Why doesn't the compiler recognize declared methods at compile time?
John Doner

This shows up as a warning because Objective-C is a very dynamic language. At compile time, the compiler hasn't found the declaration for "myMethod" (perhaps you're missing a header file, or forgot to include it in the header?) when it was attempting to compile the file. However, it only generated a warning because Objective-C has the ability to create and load extra methods at runtime so that by the time that code executes, that method will exist. Hence, it is only a warning.
Most likely you just haven't declare the method in the appropriate header file.

The warning means you're calling a method for which the compiler has not yet seen a method declaration. It is an error in most other languages, and it is certainly a warning you cannot ignore.
If you haven't declared the method, do so in an #interface block at the top of your source file (if it's a private method) or in your class's header file (if it's a public method).
If you have declared the method in a header file, be sure to import the header file.
If you have declared the method and you are importing the correct header file, you have a typo somewhere.

One case where this happens frequently is if the type of the variable that contains the object is that of a superclass, and the method is only defined for the subclass. You can avoid this by either typing it as id or making the static typing more specific. If the variable type is that of the class itself, it's likely that the method isn't visible to the compiler in the scope where you're trying to invoke it — the other answers deal with this situation.

Or sometimes, if you're using a delegate class, you need to define a category with those delegate methods in order for the compiler to find them.

Usually, adding
#class myObject1
will solve the problem. Check out Ben Gottlieb's answer to Objective-C #class vs. #import here on Stack Overflow.

Related

Some methods are not declared in .h files

I am working through the "Big Nerds Ranch" Objective-C book and noticed in one of the chapters where they are setting up an observer to listen for time zone changes they create a method in the .m file called zoneChanged however it didn't need to be declared in the .h? How can methods be used without being declared? Is it because it was only going to be triggered by the observer?
I read that if you declare a method in the .m file then it would be private however it doesn't seem to be declared at all in the .m file.
How can methods be used without being declared?
What they are doing is directly providing the definition itself. The problem is if it is not declared in the header file, any other file depending on this file isn't aware that zoneChanged function exist. However you can link it through the keyword extern and that is a different story.
As far as to the compiler, it should know what the function is in the current compilation unit, else the compiler complains. In case if you forward declare the function, you are promising the compiler the definition is else where but may or may not be before the point of call. And if you don't provide definition, linker complains.

Objective c: method relation .h and .m

I have a theoretical question: but every method and IbAction must be declared in .h??? Because if I write a method (void) in .m and not in .h the project not has problem.
If you wanna access a function from another class you're gonna import that .h header file to make your compiler understand where to find those functions and how to translate them.
It is a guideline for how to implement your classes.
Think of it in "C" terms. You define your prototypes in the .h (header) file and do the implementation in the .c or in this case the .m file.
Both ways will work, just don't redefine it in the .m...
no, they do not all need to be declared in the header.
it is common to omit the declaration from the header when attempting to make a method 'private', by categories or extensions. whether that is more or less dangerous than declaring those in the header as private is debatable, and depends on the people using your objects.
it's also good to declare a category which is not terribly relevant to the base type in a separate header.
Yeah it's no necessary to declare method in .h that because in objective c any message can be passed to any object. That's why it doesn't give any error but only a warning "ABClass may not respond to messageABC". And for a person like me who just hate warnings declare it in .h. And this is good practice as not declaring it in header is more prone to crashes as you just ignore the warnings and the instance can't handle that message and your application would say, "Hello Mr. Crash". and "Bye-Bye" to developer.

methods in objective-c

How come sometimes you need to put the method signature in the .h file and sometimes you don't?
Methods which you are overriding from your superclass do not need to be redeclared in your class's interface. It is sometimes a good idea to do so, but is not required.
Similarly, you do not need to declare methods that you are implementing from a protocol; simply declaring that you conform to the protocol is enough.
You should declare methods which are "new" to your class: those which are not inherited from a superclass nor part of a protocol. This is to give the compiler the necessary information to determine the correct argument and return types and is necessary to the correct running of your application.
Those answerers who have said that you don't have to declare your methods are technical correct, however be aware that this is a very bad practice as the compiler will infer parameter and return types which may not match the definition and can cause undefined behavior when the method is called.
This is just because some people like to put it in the header. Some people don't. You might have notice that in the .h files there is an #interface. You technically just need to put method signatures there. But, trust me, it makes life a lot easier if its in the header file (mostly because its more readable).
Because technically objects have no methods in Objective-C as we know them from other languages, instead what you are doing is to send messages to the object, if there is a corresponding method (message) on the object with the same signature, it will be called. This means there is no real need to have the signatures in the header however it is good practice to have them so that the compiler can warn if you write the wrong signature.
It's always a good idea to declare methods in the #interface before using them (it helps the compiler, allowing the compiler to help you by catching more type errors), but the header file should really only have public methods (methods you want other classes to know about). For private methods that are used internally by the class, a class extension within the .m file is a good idea, i.e.:
#interface MyClass ()
-(void) superSecretMethod;
#end
It's always a good idea to put the signature of your public methods in the .h file. You will avoid compiler warnings, and you'll know that if you do get a warning, it's for a good reason (you mistyped your method name, parameter type, etc).

Persistent warning message about "initWithDelegate"!

This is not an actual Xcode error message, it is a warning that has been haunting me for
a long time. I have found no way of removing it and I think I maybe have overstepped some unwritten naming convention rule.
If I build a class, most often extending NSObject, whose only purpose is to do some task and report back when it has data, I often give it a convenience constructor like "initWithDelegate".
The first time I did this in my current project was for a class called ISWebservice which has a protocol like this:
#protocol ISWebserviceDelegate
#optional
- (void) serviceFailed:(NSError*) error;
- (void) serviceSuccess:(NSArray*) data;
#required
#end
Declared in my ISWebservice.h interface, right below my import statements.
I have other classes that uses a convenience constructor named "initWithDelegate".
E.g. "InternetConnectionLost.h", this class does not however have its methods as optional, there are no #optional #required tags in the declaration, i.e. they are all required.
Now my warning pops up every time I instantiate one of these Classes with convenience constructors written later than the ISWebservice, so when utilizing the "InternetConnectionLost" class, even though the entire Class owning the "InternetConnectionLost" object has nothing to do with the "ISWebservice" Class, no imports, methods being called, no nothing, the warning goes: 'ClassOwningInternetConnectionLost' does not implement the 'ISWebserviceDelegate' protocol
I does not break anything, crash at runtime or do me any harm, but it has begun to bug me as I near release. Also, because several classes use the "initWithDelegate" constructor naming, I have 18 of these warnings in my build results and I am getting uncertain if I did something wrong, being fairly new at this language.
Hope someone can shed a little light on this warning, thank you:)
The cause here is that you have multiple interfaces in your project that have functions defined as initWithDelegate:(id).
Alloc only returns id, so the compiler doesn't know the type, it therefore doesn't know which initWithDelegate is being used and seemingly uses the first one in the list. Thus you get a warning that makes no sense.
The runtime knows the type of the object however, and thus doesn't have any trouble.
The solution seemingly is to use more verbose init methods, eg. initWithWebServiceDelegate. Or to cast after the alloc:
[(Foo *)[Foo alloc] initWithDelegate:self]
Your getting the warning because the compiler thinks that the classes have declared that they implement the ISWebserviceDelegate protocol. I doubt it has anything to do with the intiWithDelegate method unless your inheriting the method or you've defined the method in a protocol that itself is an extension of ISWebserviceDelegate protocol.
The usual cause of this is declaring the adoption of the protocol in a superclass and then forgetting to implement in that superclass of a subsequent subclass.
If you're sure that is not the case, then you probably just need to clean the project and rebuild. You most likely did declare at one point, then undeclared but the compiler is stuck on the old declaration.
If the clean does not resolve, I would do a project find on ISWebserviceDelegate and make sure its not tucked away somewhere.

Objective-C method implementation nuances

I have just started to develop for the iPhone and am in the process of learning Objective-C. I have seen some code that implements a method in the #implementation side of a class like this:
-(void)myMethod; {
// method body
}
What makes this interesting is that there is no mention of myMethod in the #interface for the class. I tried a sample project with this and when I compile I get a warning from XCode that myMethod may not be seen by the calling code.
Can anyone tell me what is going on?
Thanks!
It's just like functions in C. You don't need a declaration (i.e. it doesn't have to be in the #interface) but if there's no declaration, any code before the method definition will generate that warning. Code after the method definition will not generate a warning.
In ObjC, method calls are resolved dynamically (dynamic binding), meaning that when you do [obj myMethod];, internally the ObjC runtime software will go through the class methods at that point in time and if it finds one called "myMethod" it will then call it.
Also it is possible to add methods to an object at runtime.
The method declarations in an #interface section is only there to help the compiler determine what methods are publicly available for a given class. If you do add a method in your #implementation only, the compiler may warn you about that, but the code will still compile and work.
I sometimes use this to add internal methods to my objects, which are only called from other methods after it, and never from outside. Though I don't remember seeing warnings about it... Make sure that the calling code is placed after the method implementation in the same file.