How does an underscore in front of a variable in a cocoa objective-c class work?
Asked Answered
L

9

159

I've seen in a few iPhone examples that attributes have used an underscore _ in front of the variable. Does anyone know what this means? Or how it works?

An interface file I'm using looks like:

@interface MissionCell : UITableViewCell {
    Mission *_mission;
    UILabel *_missionName;
}

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

I'm not sure exactly what the above does but when I try to set the mission name like:

aMission.missionName = missionName;

I get the error:

request for member 'missionName' in something not a structure or union

Lemonade answered 4/5, 2009 at 22:48 Comment(0)
S
100

If you use the underscore prefix for your ivars (which is nothing more than a common convention, but a useful one), then you need to do 1 extra thing so the auto-generated accessor (for the property) knows which ivar to use. Specifically, in your implementation file, your synthesize should look like this:

@synthesize missionName = _missionName;

More generically, this is:

@synthesize propertyName = _ivarName;
Scintillator answered 4/5, 2009 at 23:40 Comment(7)
with auto-synthesizing properties this is no longer necessary. Xcode synthesizes a @property xxxx with an ivar named _xxxx behind the scenes. Neat.Shoal
@LearnCocos2D Hi! A newbie to iOS here and there's something I need to clarify. For all this time what I did was declare the property in the .h file and in the .m fie I access it using self like so, self.someProperty. Is this the right way? Or should I be using the ivars in the code?Vanadium
setting the ivar doesn't run the property setter - you decide whether that is good idea or not for each particular caseShoal
Noob question: why not use the ivars directly? why should I declare a separate var to hold the ivar?Neomaneomah
@Allen, if I understand your question correctly: The separate var you're declaring is a pointer to the actual variable. This is important for a few reasons (that I know of) Firstly, when you pass a pointer into a function you're not duplicating it's value. You're simply telling the function where to find the value to use. This helps keep your used memory low (and also helps with alloc and dealloc of memory, which is important in the absence of 'garbage collection' which you'll find in Java)Rede
There are also some neat tests you can run about the integrity of changing values when you access them directly. (Due to copies being made, often your original var will not change when you manipulate it)Rede
@LearnCocos2D, no, you don't decide whether that is good idea or not, as Apple states it hereDefiniens
G
19

It's just a convention for readability, it doesn't do anything special to the compiler. You'll see people use it on private instance variables and method names. Apple actually recommends not using the underscore (if you're not being careful you could override something in your superclass), but you shouldn't feel bad about ignoring that advice. :)

Gyrostabilizer answered 5/5, 2009 at 2:10 Comment(4)
From what I understand, Apple recommends against using the underscore prefix on method names (they reserve that for themselves as a convention for private methods), but they don't have any such recommendation about instance variable names.Scintillator
@Scintillator In fact, Apple encourages to do so: "Usually, you should not access instance variables directly, instead you should use accessor methods (you do access instance variables directly in init and dealloc methods). To help to signal this, prefix instance variable names with an underscore (_), for example: \@implementation MyClass { BOOL _showsTitle; }"Andrade
I actually dont think Apple encourages us to do so, since all their own sample codes in the iOS Developer Library dont have the () in them. Apple also says that they have reserved it, which must mean that they use it internally for their own frameworks like UIKit etc. Which is why we shouldn't carelessly use it. But I see that, in the link you provided @kelan. They actually say in the "revision history" that it is "suitable" to use (). I interpret is as we "can" use it if we want.Nellnella
Apple's documentation which says not to use the underscore prefix for method names is here.Mcadoo
S
9

The only useful purpose I have seen is to differentiate between local variables and member variables as stated above, but it is not a necessary convention. When paired with a @property, it increases verbosity of synthesize statements – @synthesize missionName = _missionName;, and is ugly everywhere.

Instead of using the underscore, just use descriptive variable names within methods that do not conflict. When they must conflict, the variable name within the method should suffer an underscore, not the member variable that may be used by multiple methods. The only common place this is useful is in a setter or in an init method. In addition, it will make the @synthesize statement more concise.

-(void)setMyString:(NSString*)_myString
{
    myString = _myString;
}

Edit: With the latest compiler feature of auto-synthesis, I now use underscore for the ivar (on the rare occasion that I need to use an ivar to match what auto-synthesis does.

Snaggy answered 16/6, 2011 at 1:58 Comment(4)
It the other way around. private variable is underscored. the property not. and whem synthesizing them you couple them.Pilchard
That is exactly as I describe, except that I called it a "member variable" instead of a "private variable".Snaggy
Ouch! This is asking for trouble… auto-synthesis will make the ivar _myString which means your setter won't work (because it then won't be able to tell your ivar from the method parameter).Guardrail
Correct, which is why I added the edit at the end when apple added auto-synthesis.Snaggy
A
5

It doesn't really mean anything, it's just a convention some people use to differentiate member variables from local variables.

As for the error, it sounds like aMission has the wrong type. What it its declaration?

Access answered 4/5, 2009 at 22:51 Comment(4)
It's common in IDE's with intellisense; it will make your member/module/class variables show at the top of the list. Another common previx is "m_"Plagiarize
if it doesn't mean anything how can you switch back and forth between _missionName and missionName like in my example above? My declaration looks like: Mission *aMission = [[Mission alloc] init]; aMission.missionName = @"a mission";Lemonade
One is an instance variable and the other is a property. You can't access instance variables with syntax like aMission.missionName, because that syntax doesn't work with pointers.Belaud
Also, note that you are trying to operate on a Mission object, but the interface you have posted with the missionName property is a MissionCell.Access
S
2

This is only for the naming convention of synthesize properties.

When you synthesize variables in the .m file, Xcode will automatically provide you _variable intelligence.

Soteriology answered 5/7, 2013 at 6:16 Comment(0)
B
1

Having an underscore not only makes it possible to resolve your ivars without resorting to using self.member syntax but it makes your code more readable since you know when a variable is an ivar (because of its underscore prefix) or a member argument (no underscore).

Example:

- (void) displayImage: (UIImage *) image {

    if (image != nil) {
        // Display the passed image...
        [_imageView setImage: image];
    } else {
        // fall back on the default image...
        [_imageView setImage: _image];
    }
}
Broadway answered 19/4, 2012 at 5:13 Comment(2)
In this example it would be nice to see a comparison of the use of self.image (or [self image]) as well. When is it better to use self.image and when is it better to use _image?Equivalent
@Boeckm: Generally, you should use self.image, which accesses the property. The only time you should access the instance variable, _image, directly is within init methods and the dealloc method, when calling any other method may be risky (since the object is half-initialized or half-deallocated).Gabrila
F
1

This seems to be the "master" item for questions about self.variableName vs. _variablename. What threw me for a loop was that in the .h, I had:

...
@interface myClass : parentClass {
className *variableName;    // Note lack of _
}

@property (strong, nonatomic) className  *variableName;
...

This leads to self.variableName and _variableName being two distinct variables in the .m. What I needed was:

...
@interface myClass : parentClass {
className *_variableName;    // Note presence of _
}

@property (strong, nonatomic) className  *variableName;
...

Then, in the class' .m, self.variableName and _variableName are equivalent.

What I'm still not clear on is why many examples still work, even tough this is not done.

Ray

Fess answered 29/1, 2013 at 14:20 Comment(0)
A
0

instead of underscore you can use self.variable name or you can synthesise the variable to use the variable or outlet without underscore .

Allard answered 24/4, 2015 at 13:51 Comment(1)
if you only need the variable in the same class just declare it in .m file itself then it will allow you to call without self nor the underscoreFortune
C
0

Missing from the other answers is that using _variable prevents you from absentmindedly typing variable and accessing the ivar rather than the (presumedly intended) property.

The compiler will force you to use either self.variable or _variable. Using underscores makes it impossible to type variable, which reduces programmer errors.

- (void)fooMethod {

    // ERROR - "Use of undeclared identifier 'foo', did you mean '_foo'?"
    foo = @1;

    // So instead you must specifically choose to use the property or the ivar:

    // Property
    self.foo = @1;

    // Ivar
    _foo = @1;

}
Cooker answered 29/9, 2015 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.