Persistent warning message about "initWithDelegate"! - cocoa-touch

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.

Related

If Protocol method is marked #required, when not implemented, why does compiler issue a warning and not an error?

Assume that:
New Protocol is declared
Method in this protocol is marked #required
Class conforms to Protocol
Class does not implement the method mentioned in Protocol
At compile time, information about this method is known: i.e. that it is required and that this class and any other classes this class may may extend do not implement it.
Why in this case the compiler issues a warning and not an error?
Errors are only issued when the compiler cannot continue because something went terribly wrong.
When calling a method in Objective-C, the method lookup is done during runtime and not during compilation, which C++ does. In Objective-C a "message" is simply sent to the object, something like obj.executeCommand("Hey, can you execute function <name> for me?"). In C++ the object will be called directly, in a way like obj.<name>(). In the case of Objective-C the executeCommand() method is called, which exists. In C++'s case the function is called but it does not exist. These are methods that are linked on the compiler level, which means they both become memory addresses rather than names. executeCommand becomes 0x12345678 but it still uses the same message ("execute function <name>").
This is probably very confusing, but it's related to the way methods are implemented in different languages.
If you feel strongly about it, why not turn on -Werror?
I don't know the real answer but here is a use case that would go against it.
What if you implemented all of the protocol methods in a category???
Main interface declaration adopts the protocol however the protocol method implementation is in a category.
This is valid code but will show compile error if compiler was that strict !!
Objective-C is a dynamic language. The idea of what an implementation is, is different to a static language.
For the most part, it's in code that most of us implement inside the #implementation ... #end block.
But what if a method is not found? Then an object has a chance deal with it dynamically.
Imagine you have an interface for a sound effect player:
#protocol FX
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
#end
An implementation could have the files Beep.mp3, Siren.mp3, Honk.mp3 to play, but instead of implementing each of the methods, it could override -forwardInvocation: and parse the selector string, something like this pseudocode:
NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:#"play"]) {
NSString filename = fileNameFromSelector(selName);
[self playSoundFileNamed:filename];
}
This may seem contrived, but once you start using the dynamic features of the language, you will start finding more and more places where it makes sense. And by sense I mean, does this effort help in the long run?
In the above case, just add a -sound* method name to the interface, and drop in a appropriately named sound file. It just works.
Another example from personal experiments: how to deal with Core Data entities in a more natural way. I want to do this:
NSArray *people = [Person findAllWithNameLike:#"B%"];
instead of mucking about with predicates, fetch requests etc.
But I don't want to define every permutation of method in code.
How about if I wanted to build an XML builder? I would look at a dynamic approach. It has served Groovy Builders well (look at Groovy/Grails for examples).
One last example: I have a traits system where I can define behaviours in the form of groups of methods and have my objects assimilate this behaviour. So, while the compiler doesn't see an implementation for the interface my object conforms to, the implementation is injected into it from a trait class, using the Objective-C runtime. Why would I do this? I find many delegate methods are boiler plate, but at the same time, a single base class for each situation is not flexible enough. Instead of cut and paste from code samples, my 'samples' compile and run :) and any changes are reflected across all projects using the trait.
To really understand why all this is available to you, it is worth playing around with a Smalltalk environment (search Pharo or Squeak). This is where Objective-C has its roots.
And finally, to stop these warnings:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"
#implementation ... #end
#pragma clang diagnostic pop
Because there are times when there are bogus "required" methods in a poorly designed protocol.
They should have been optional but someone insisted they are "required".
Thusly making this a run time issue rather than a compile bug is very very wise.

Objective-C: my class with static methods "does not implement methodSignatureForSelector: -- trouble ahead"

I have a utility class which has only static methods, so it is not inheriting from NSObject (No need right?)
There are no warnings at all when compiling.
The problem comes when running on the iPhone simulator. It crashes with warning "does not implement methodSignatureForSelector: -- trouble ahead"
Well, I like that "trouble ahead" thing, I never heard a debugger telling me that there's "trouble ahead".
But what I don't like is the error itself... Why is it expecting me to implement methodSignatureForSelector in a class when I clearly call a static method? (+)
Thanks!
Daniel
This is not an idiomatic pattern in Cocoa. I would strongly recommend you rethink your design. This is not Java or C++. For one thing, there isn't even such a thing as a "static method" — they're class methods, with the class being an object itself.
It's also very weird to have a class that's not a subclass of NSObject ("no need" is not a very rational reason for deviating from the default behavior), and even weirder to have a class with only class methods. The class should probably either be a singleton or else eliminated and its methods turned into functions, depending on whether it needs to keep state.
As for the exact reason you're crashing, it's hard to say without seeing your code. That warning by itself should not crash your program. You do need to have some implementation of +initialize, even if it does nothing, because the runtime sends that message to every class that receives a message. That's probably where the error is coming up — you send a message, the runtime tries to send initialize, your class doesn't respond, the runtime tries to invoke the forwarding machinery and can't.
Thanks for the answer!
About the 'static' vs. 'class methods', AFAIK this is just naming, no real difference. Like 'functions/methods' and 'messages'.
However, this is not necessarily 'incorrect' design.
First you have to remember that ObjC has no namespacing, so the only way to put some order into things, is a class. Because if two functions' names collide, the compiler will shout loudly.
There ARE sometimes some functions that are 'Utility' functions and work on other objects, or do certain calculations, that can't be directly related to a certain object to manage them, and also they shouldn't, because that will just generate unnecessary overhead.
As a very experienced C/C++/Asm/Others prorgammer, when programming in ObjC, I tend to always release memory myself, for performance reasons.
For the same reasons, I wouldn't want to generate any overhead where its not needed. And ObjC has a lot of overhead.
The docs also do not say that I MUST inherit from NSObject, it says that I SHOULD when I want it to be correctly managed by the framework.
But as I understand it there's no need for any managing, these functions should be just functions wrapped inside a classname's namespace.
About +initiallize - that can only be overridden if the class inherits from NSObject. So the original question is still there - why should I inherit from NSObject if I do not want any of its services? I do not need to allocate the class or init it, as I have nothing to do with an instance of it!
Also a weird thing in ObjC is that you can override a class method?!

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).

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.

Why declare a method in a Category without implementing it?

I'm reading the source code of an open-source project and I've encountered the following category definition in an implementation file:
#interface QCView (Private)
- (void)_pause;
- (void)setClearsBackground:(BOOL)flag;
#end
At first I thought that the setClearsBackground method was being added to the QCView class definition. But when I search through this implementation file, I find no implementation of a setClearsBackground method (although this message is sent to a QCView instance in a few places within the file).
Why would someone declare a method on a framework class like QCView but then not implement that method anywhere? My only guess is that this is a way to circumvent the compiler and call a method that isn't declared in the QCView.h file. But this seems unlikely, because how would the developer know that an implementation for this method even exists?
The developer probably used a tool such as class-dump in order to generate headers which list all the methods implemented by a framework. This is useful if you need to access SPI and have no other choice. Without the declaration, Objective-C makes assumptions about the method parameters and, beyond generating a warning, may generate an incorrect method invocation.
All the usual caveats about an undocumented interface breaking in a future OS revision apply. At the minimum, you should check if the object responds to that method (-[NSObject respondsToSelector]). For extra paranoia you can wrap the invocation in an exception block, in case the method remained but its behavior changed.