Some methods are not declared in .h files - objective-c

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.

Related

Why do I need a class extension to make a method private?

I've been reading a little bit about this and what I don't understand is why people adds class extensions to make a method private.
Wouldn't it suffice to just leave it out from the header file?
It looks to me to be enough, but I might be missing a bigger point?
Short answer: now (as of Xcode 4.4, I think), you don't. Reason: you don't need to forward declare methods. Put your private methods in your .m file, and you're done.
Previously (Xcode 4.3 and older), you had to forward declare your methods before you could call them. Because you already declared the class in the .h file, you can't declare it again in the .m file, so a class extension is the way to add methods to an already declared class.
Edit: as #Yar mentioned above (and below), a private method in a .m file that isn't declared would not be visible to subclasses of that class, meaning it would be impossible for that subclass to call or override that method. Still, I'd be inclined to just not bother declaring it, unless/until you end up with a subclass that needs to override or call it. For me this happens pretty infrequently.
It would be sufficient to leave it out of the header file, but then your subclasses don't know it's there, either. This means that you get a compiler error if you try to call these private methods. This is why you use an external file that is a class extension, and all subclasses import that extension in the .m file.
Obviously, this situation is not ideal because you get three files for each class, minimum, but the joy of Objective-C is about making LOTS of files and not worry about it. If you are scared to make files, you will end up with big classes, which is an anti-pattern.
One problem is naming the class extension file, since it's a category with no, um, category. I've been using a scheme like Blah4Subclasses, which is probably about as bad a suggestion as you'll get.
the class continuation has nothing to do with access, wrt the translation. the objc language does not specify access for methods. so it's a relatively weak private. what people end up falling back on is the ability to hide method declarations in their implementation file.
the important point to take away is that the class continuation is generally only visible to your class (because it is often placed in the *.m file). this pattern reduces the likelihood of a private method's use because it is not visible to the client, or to the compiler (in translations other than the one which contains the class' #implementation in the typical structure).
also note that the class continuation is capable of a lot -- so it's a convenient place to store your private #interface; properties, ivars, methods.
lastly, it is also a habit from earlier days, because it was a more frequent necessity. not too long ago, the declaration was added so the compiler knew the object responded to a specific selector, and the signature of that selector. because clang parses the entire #implementation block these days, many people find they do not need the declarations in the class continuation because the compiler can match methods seen in the #implementation, regardless of order of declaration.
You can add #private in your .h file.

How to automatically verify all methods are declared in xcode

I am working with Objective-C in Xcode. I was wondering is there any mechanism to proof your code to make sure all functions and methods are declared in the .h file or in the private #interface method?
To clarify I will be on a coding tangent and will write a method directly in my viewController.m file
- (Awesome*) generateAwesomeOfMagnitude:(NSFloat)magnitude { ...
and I will forget to add the heading to the viewController.h file. If this is a private method nothing notifies me that I've done this so I have to go back through and verify that everything was declared manually when Im done. Is there any way to check automatically?
Note: Im looking to make the complier to throw a warning. Is there a setting is really what I should have asked.
Omar's answer is correct - asking an object if it will respond to a selector is the preferred method for probing objects to see if they'll respond to a method at runtime. However, the question asks "How to automatically verify all methods are declared?" (presumably at compile time). And the answer is, short of writing something yourself, you cannot automatically do this.
This is part of what makes Objective-C 'dynamic'. You don't have to declare a method anywhere. This makes things possible like:
id anUnknownObject = [[NSClassFromString(whoKnowsWhatIllBe) alloc] init];
[anUnknownObject performSelector:#selector(whoKnowsWhatIllDo)];
This means, for example, you could fetch a string from a web service and instantiate a class based on the string alone (of course the class must be around at run time in order to be instantiated, but the compiler doesn't have a clue).
This doesn't mean you should program this way, but it means its possible, and, as with most things, there are appropriate use cases, and it's a great distinction of the language. It promotes extreme decoupling, polymorphism, and tons-o'-fun patterns.
It's generally regarded as best practice to declare private methods in .m class extensions, but the value of this is for the programmer, not the compiler. Some (to include a major contributor to Objective-C who shall go nameless in public forums for the time being) have also suggested that there isn't a need to type the names of all your methods twice in a single file (less code, less mistakes -a bit more scrolling if you're looking at someone else's class for the first time). Having a nice-n-tidy public API is exactly what the header is for. Having a clean implementation is important, but the assumption is that once you're in the m, you're in private territory anyway. Scroll around. See what the method names are.
To check if method exists at run time in the class use
if([yourObject respondsToSelector:#selector(generateAwesomeOfMagnitude:)])
//has this method
else
//does not have this method
but you dont get any warning if you define a method in the .m and dont include it in the .h file
However if another class is accessing a method that is not declared in the .h file you will receive a warning

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.

Objective-C: Is it ever Kosher to declare instance variables in the implementation file?

I've noticed that I'm able to declare instance variables in the implementation file of an Objective-C class. I understand there's a reason why I've been taught not to do this. Explained here. But it's so much nicer to not put them in the header, and my code seems to be running fine. How is this going to bite me in the butt down the road?
There are two ways of declaring them in the implementation file.
Through a class continuation, which means placing another #interface block at the top of the file with an empty category name (they only JUST added the ability to add ivars here)
Or placing them just at the top of the file. When doing it like this, you are NOT adding ivars. This is the same as adding a variable to the top of a C file. They are in scope of the entire file, and every instance of the class that is in that file. These are global.

Redundant Compiler Warnings

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.