views:

320

answers:

3

I'm some what confused as to the difference between accessing an instance variable via self or just by name (when working inside the class).

For instance, take this class:

.h:
@interface Register : NSObject {
    NSString *mName;
}

- (id) initWithName:(NSString *) name;

.m:
- (id) initWithName:(NSString *)name
{
    if (self == [super init])
    {
        mName = name;
    }
    return self;
}

What's the difference between accessing the instance variable via

self.mName = name;

vs

mName = name;

Which isn't a @property and is not @sythenize'd.

Say it is this though, per this example:

.h:
@interface Manange_My_ViewsViewController : UIViewController { 
    IBOutlet UILabel *countLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *countLabel;

.m:
@synthesize countLabel;

- (void) updateLabel:(NSUInteger)count
{
    countLabel.text = [NSString stringWithFormat:@"%d", count];
}

But say I accessed countLabel as:

self.countLabel

What would be the difference?

Edit: Third example per users' answer: Say it the iVar wasn't an IBOutlet:

.h:
@interface Fake : NSObject {
    NSString *mVar;
}
@property (nonatomic, retain) NSString *mVar;

.m:
 @synthesize mVar;

 mVar = @"";

VS

 self.mVar = @"";

Or is it the same - that in the first we are accessing the actual instance variable and in the second we're actually going through the auto created setter (via @synthesize)?

Thanks all!

Edit: Update in response to Peter Hosey ...

So your thinking the convention of mVarName is bad? I took that from my C++ days.

But what about the case when you do?

-(void) someMethod:(int) x
{
    x = x;
}

You can't do that (Say 'x' is also a class variable)

But you can do:

-(void) someMethod:(int) x
{
    mX = x;
}

But your saying its better to do:

-(void) someMethod:(int) x
{
    self.x = x;
}
+1  A: 

First of all, with a read-only property--which an IBOutlet essentially is--it does not matter as much.

The key difference is that the property is actually calling the accessor method while the instance variable is being accessed directly.

Thus, for setting a retain property, using self and the accessor will release the old object and retain the new one. Setting the instance variable directly will NOT impact the retain counts of any objects.

Using @synthesize will generate standard accessors for you.

The key reason to use properties is that, since they are accessors, they can be read and/or modified from outside the class.

gerry3
Ok - makes sense. What about if that wasn't an IBOutlet (Adding a 3rd example to my question).
Mr-sk
I have made some updates to my answer.
gerry3
""The key reason to use properties is that, since they are accessors, they can be read and/or modified from outside the class."" - ok but what about inside the class. Is it better to access them via self.iVar or just as iVar?What's considered best practice?
Mr-sk
I think it depends on the situation. Keep in mind the difference though. If you are allocating and initializing a new object, you can assign that directly to the ivar, but with a retain property, you would have to release the object or you would be leaking.
gerry3
@gerry3 even with a `retain` property, you still have to release it in your `dealloc` method.
Dave DeLong
@Dave True, but I meant you also have to release it right away since it is returned from alloc with a retain count of 1 and you increment that by setting the property. Of course, this is not the case if you use a convenience constructor and get an autoreleased object back.
gerry3
+2  A: 

OK, first off is the basic difference:

mVar = var;

This is just changing a value. That's it.

self.mVar = var;

This is equivalent to:

[self setMVar:var];

In other words, one invokes a method, the other does not. Using the @property syntax can give you some really neat benefits. For example, you get key-value coding compliance for free. That means that another object can observe this object's mVar property, and be automatically notified whenever it changes, without you doing anything. You don't get this if you just access the ivar directly. (Unless, of course, you implement it yourself. But why would you do that?)

You also get semi-free memory management. If you declare a property as (retain), then you don't have to [newValue retain] yourself. The synthesized method will do this for you (in both cases, you'd still have to [ivar release] in your dealloc method).

You also can get some degree of thread safety. If you don't declare a property as (nonatomic), then it is (by default) atomic (although that keyword does not exist; it's implied). That means that reading/updating the value of the property is an atomic operation. If you were to just access the ivar directly, you'd have to implement the atomicity yourself with a lock.

Basically, using the synthesized methods gets you some really neat stuff for free. The only reason I'd say to not use the @property syntax is if you have irrefutable evidence that invoking those methods is a bottleneck in your code. However, you'll be really hard pressed to come up with a situation where that would be the case.

Dave DeLong
+5  A: 

What's the difference between accessing the instance variable via

self.mName = name;

vs

mName = name;

The first is property access syntax. It translates to an accessor message to the object (in this case, self). That is, that statement implicitly translates to this message expression statement:

[self setMName:name];

(Awkward accessor names like that are why “mName” is a poor name for a property. There is property declaration syntax to work around that, letting you name the property “name” and your instance variable “mName” and map one to the other.)

The second example directly accesses the instance variable—no accessor message.

Which isn't a @property and is not @sythenize'd.

Say it is this though, …

If no property named “mName” is declared for a class, then you can't use property access syntax to access a property by that name on an instance of that class.

And it doesn't matter whether you synthesize the accessors, hand-wave them to a superclass with @dynamic, or define them yourself. That's how the object will respond to the accessor message, but the accessor message the compiler generates will be no different (since a property access could just as easily come from outside the class as from inside it).

Say it the iVar wasn't an IBOutlet:

That doesn't matter. IBOutlet only means anything to IB. Everything else doesn't care.

In fact, IBOutlet is currently just a macro that expands to nothing. After your code gets preprocessed, the word “IBOutlet” is no longer there, so the compiler never sees it. That's how little a difference it makes to anything but IB: None at all.

Edit in response to question edit

I said mName is bad as a property name, because of the accessor names that follow from it. The name of an instance variable is a separate issue, particularly since the property and ivar don't have to have the same name.

For a variable, be it an instance variable or a local variable, the choice of name or m_name or mName is purely a style choice.

someMethod: is generally the accessor, setX:. Within that method, self.x = x, which is [self setX:x], causes infinite recursion. So don't do that.

When someMethod: isn't the accessor (or init or dealloc), using the property is just fine and generally preferable. However, in that case, you're not likely to give one of its arguments the same name as an instance variable. When such a case could occur, name the local variable more specifically, because its purpose is more specific. This, too, is a style issue.

When it is the accessor, I name the local variable newX, having named the instance variable the same as the property, x. This is my own personal style; as I said, naming the property x, the ivar mX, and the local variable x is fine too (aside from the excessive brevity of this example).

Peter Hosey
Thanks. I updated my question, please see above. = ]
Mr-sk
Huh? You can't do property access on an `id` variable — the compiler will error out along the lines of "error: request for member ‘count’ in something not a structure or union".
Chuck
Bad example (I don't think anything in Cocoa has a property named `count`, so it would be entirely reasonable to at least warn on that), but you're right—I just tried it with a known-existing property and got that result. And now I think I remember bbum posting a reason why awhile back. Thanks for the prod to check that claim; I'll edit it out of my answer.
Peter Hosey