1

I've noticed that I get compilation errors if I place certain declarations in certain places in my header file. I've put comments into the code as to where I think certain things go; are they correct?

@interface Level : CCNode { 
    //Instance variables?
    PlayBackgroundLayer* playBGLayer;
    PlayUILayer* playUILayer;
    PlayElementLayer* playElementLayer;
}

//Static methods?
+(void) InitLevel: (int) levelNumber;
+(Level*) GetCurrentLevel;

//Property declarations for instance variables?
@property (nonatomic, retain) PlayBackgroundLayer* playBGLayer;
@end

//Static variables?
Level* currentLevel;
PlayTilemapLayer* playTilemapLayer;
jscs
  • 63,694
  • 13
  • 151
  • 195
williamsandonz
  • 15,864
  • 23
  • 100
  • 186

2 Answers2

1

Instance variables usually don't need to be declared explicitly. They're created when you @synthesize the property. If you do want them, though, the (new) correct place* is at the top of the implementation block:

@implementation Level
{
    PlayBackgroundLayer* playBGLayer;
    PlayUILayer* playUILayer;
    PlayElementLayer* playElementLayer;
}

Those aren't static methods, they're class methods, but, yes, that's where you declare them. Some people like to put @property declarations before the class methods, but that's a matter of opinion. Instance methods go after both of these, although technically speaking the order doesn't matter -- that is, the compiler doesn't care, it's just a matter of readability.

Those top-level variables need to go somewhere other than a header file, though. If you put them there you will get compilation errors because every file that imports the header will appear to be re-declaring storage for those variables, which isn't allowed.

Ususally you put such variables into a .m file. If you want them to only be visible from there, you would use static. If you want them visible from other files that import the header, you leave static off and declare the variable as extern in the header:

extern Level* currentLevel;

This lets the compiler know that the storage for the variable is reserved elsewhere.


*See "Class Interface" in TOCPL.

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
  • Is that really the new correct place? I was aware of the change but are we being encouraged to put them in the implementation instead of in the interface or interface private category? – borrrden Jun 13 '12 at 01:31
  • @borrrden: Yes, see the link I've made to TOCPL, especially the "Historical note" in that section. – jscs Jun 13 '12 at 01:34
  • I've had a habit of moving all my private instance variables to the `@interface Foo ()` section of the .m file. However, I believe protected instance variables (that should only be available to child classes and not exposed through properties) should still go in the header file, correct? – borrrden Jun 13 '12 at 01:43
  • It's true that the implementation-block ivars are `@private` by default, but that can be changed to `@protected`. Certainly if you're planning to make your class subclassable by other developers, you may need to leave some ivars in the header. – jscs Jun 13 '12 at 01:47
1

You are correct on all counts except one. Your last variables are not static variables, they are global variables. Static variables are simply variables that are declared with the static keyword and they mean something a little different than other languages. They aren't class variables, they are variables that are visible only to the file that they are declared in, and only then in the scope that it was declared (if you declare it inside a function other functions won't see it). However, as you would expect, they are only declared once regardless of how many instances you have. If you declare something outside an interface without the static keyword as you did, other classes will import them. However, this is not the ideal way to accomplish this (you might get redefinition errors if more than one class imports this header).

Also, one caveat, is that properties don't need to have an explicit backing variable (the compiler will create one for you if you use the @synthesize keyword), but of course if you desire one there is nothing wrong with it.

Finally, you should note that the only reason that your static methods class methods are not instance methods is because they start with a plus (+) character as opposed to a minus (-) character.

borrrden
  • 33,256
  • 8
  • 74
  • 109
  • Not static methods, class methods. – jscs Jun 13 '12 at 01:31
  • I've been using the two terms interchangeably...could you point out the difference? – borrrden Jun 13 '12 at 01:33
  • :) See the link to bbum's post in my answer. Roughly, there are no static methods in ObjC -- people just call them that because in other OO languages, static methods sort of fill the role that class methods do in ObjC. Class methods are actually instance methods of the meta class. – jscs Jun 13 '12 at 01:35
  • @JoshCaswell I see, well I'd like to use the correct terms in that case. Is it impossible to declare a static method in Obj-C then? The closest thing would be a static function I suppose (in C) – borrrden Jun 13 '12 at 01:40
  • It isn't. There certainly are `static` functions, which, as in C, have limited visibility. – jscs Jun 13 '12 at 01:43