5

I have reviewed many code samples and have found that people commonly declare all methods and global variables in the header (.h) file. Is it necessary?

Jeremy
  • 8,902
  • 2
  • 36
  • 44

3 Answers3

11

Methods to be used publicly (i.e. by classes other than the class implementing the method) and (truly) global variables should indeed be declared in the header file. The whole point is that you can import the header file in another source code file to gain access to the functionality declared there.

Methods that are meant to be private -- that is only to be called as part of the internal implementation of a class -- can be declared in a class extension. With recent versions of LLVM/Xcode, you actually don't even need to do that for non-@property methods. You can simply implement them and the compiler will be smart enough to see that they're there when called from other methods in the same class's implementation.

If you need to explicitly define a private ivar (rare these days), you can do so in a brace-enclosed section immediately after @implementation or @interface ClassName ().

In short: declare methods, functions, and variables that need be accessible from other classes in the .h file. Private methods and variable should be kept private by declaring them only in the .m file.

Andrew Madsen
  • 21,309
  • 5
  • 56
  • 97
  • Curious why you claim that private ivars are rare these days. My classes are full of them. Do your classes have no state? How do you avoid ivars? Perhaps you create a bunch of private properties instead. Now I ask why you do that? With ARC, private properties have no benefit over just having private ivars. – rmaddy Feb 13 '13 at 00:35
  • 2
    I'm pretty firmly against direct ivar access outside of accessor methods for a number of reasons besides memory management, so yes, I use private properties almost exclusively. (Code readability, ease of later making properties public (including KVO compliance), custom behavior on set, and lazy instantiation, are a few of the reasons I still much prefer to use accessor methods for all ivar access.) – Andrew Madsen Feb 13 '13 at 00:51
  • May I ask why you are against direct ivar access? I'm curious what you think the pros/cons are (other than memory mgmt). Thanks. – rmaddy Feb 13 '13 at 00:56
  • Sorry, I edited my earlier comment to provide a few reasons before I saw your most recent comment. Not a lot of space here to explain in more detail. Of those, the biggest for me may be code readability. I find it useful to know at a glance that an assignment statement is changing class state instead of a method-local variable. Being able to easily do things in response to any change to an ivar/property by adding some code to the setter is also something I do very often. Finally, I still work on two large codebases that support 10.5, so I'm not able to use ARC in all the code I write anyway. – Andrew Madsen Feb 13 '13 at 01:08
  • Thanks for your thoughts. It's funny. When I reread your updated first comment I thought code readability was the least useful reason of your listed reasons. Then in your later comment, you state readability if the biggest reason. :) I use underscores for all ivars so readability is handled that way for me. I don't want to keep going off on a tangent. Thanks again. – rmaddy Feb 13 '13 at 01:19
  • For what it's worth, this question of direct ivar access came up in a new question today, and I wrote a lengthy [answer](http://stackoverflow.com/a/14904463/344733) expounding on the reasons I gave above. – Andrew Madsen Feb 15 '13 at 22:40
5

In recent versions of the SDK, you don’t have to declare methods that you only use internally to the class, so that can cut down clutter in your .h file. In general, the only methods, properties, and ivars that I put in my .h are the ones that I know other classes will need access to. That way, I never make the mistake of externally accessing a property that is supposed to be internal-only. The rest, I put in a class extension in the .m file like this:

#import "MyClass.h"

@interface MyClass ()
{
    int _myIvar; // I rarely use these anymore,
                 // but if you want to use them, they go here.
}

@property (strong, nonatomic) NSArray *someArray;
@property (strong, nonatomic) NSDictionary *anotherProperty

@end

@implementation MyClass

@end
Zev Eisenberg
  • 8,080
  • 5
  • 38
  • 82
  • You can also declare ivars at the beginning of the `@implementation` block. – jscs Feb 13 '13 at 00:16
  • Even with older version of the SDK (really older compilers) you never needed to put private methods and properties in the .h file. You did need all ivars in the .h with older compilers. But never private methods and properties. – rmaddy Feb 13 '13 at 00:31
0

Header files have no special significance at all to the compiler. The preprocessor just copy-pastes them into the implementation file when you write #import anyway.

Catfish_Man
  • 41,261
  • 11
  • 67
  • 84
  • 2
    They actually do have special significance. Like Andrew points out, public methods and properties are supposed to be created here. The implementation file does import the header, but when you refer to methods in other classes, you always point to the methods and properties in the header file of the other class. – LJ Wilson Feb 12 '13 at 23:49
  • 1
    Hmm. Idiomatic significance, yes, but the compiler doesn't care about idioms. I suppose I should say "are no different to the compiler" – Catfish_Man Feb 13 '13 at 00:12
  • Try declaring a property only in the implementation file and then try to reference that in another class and see if the compiler sees the difference :) – LJ Wilson Feb 13 '13 at 00:14
  • Import the implementation file and it'll find it just fine. It cares what you import, not what the extension is. (Note that there may be other problems, of course, if the file contains what .m files typically do) – Catfish_Man Feb 13 '13 at 00:28
  • (There's actually a place in Adium that does [did? can't remember if I deleted that or not] #import a .m file. Gross eh?) – Catfish_Man Feb 13 '13 at 00:41