iOS: Usage of self and underscore(_) with variable [duplicate]
Asked Answered
S

3

10

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

I have been very confused with using self or underscore with variable name after synthesizing it like below:

In .h file:
@property(nonatomic, strong) NSMutableArray *users;

In .m file:
@synthesize users = _users;

Based on my understandings when I use self.users, OS will make sure to release previously allocated memory in set method so we don't need to take care explicitly.

_users is an instance variable for users and should be normally used while accessing the users variable. If I use _users to change its value then it won't fire KVO delegate which will not notify a class observing users value change.

Moreover, self.users allows differentiating dummy variable in the method name like below,

- (void)assignUsers:(NSMutableArray*)users {
      self.users = users;
}

Could someone please tell me if there is anything that I understood wrong or missing while using _users or self.users?

Sapindaceous answered 29/8, 2012 at 9:53 Comment(1)
Hi @qegal I went through that thread and if you read my question, most of points are the conclusion points but what I couldn't get is when to use what!Sapindaceous
V
9

I think it helps to consider how properties are (or might be) implemented by the compiler.

When you write self.users = array; the compiler translates this to [self setUsers:array]; When you write array = self.users; the compiler translates this to array = [self users];

@synthesize adds an ivar to your object (unless you added it yourself), and implements the -users and -setUsers: accessor methods for you (unless you provide your own)

If you're using ARC, -setUsers: will look something like:

- (void)setUsers:(NSArray *)users
{
    _users = users; // ARC takes care of retaining and release the _users ivar
}

If you're using MRC (i.e. ARC is not enabled), -setUsers: will look something like*:

- (void)setUsers:(NSArray *)users
{
    [users retain];
    [_users release];
    _users = users;
}

* - Note that this is a simplified, nonatomic implementation of -setUsers:

Vankirk answered 29/8, 2012 at 10:50 Comment(1)
The only answer on this topic that talks about the difference from a reference counting perspective with such elegance. Excellent.Fantasize
C
31

when you are using the self.users, you access the property via the setter or getter.

when you are using the _users, you access the property directly skip the setter or getter.


here is a good demonstration of it:

- (void)setUsers:(id)users {
    self.users = users; // WRONG : it causes infinite loop (and crash), because inside the setter you are trying to reach the property via setter
}

and

- (void)setUsers:(id)users {
    _users = users; // GOOD : set your property correctly
}

this is the point in the case of the getter as well.


about the basic memory management (in case of MRR or ARC): the iOS will dealloc the object if there is no more strong pointer which keeps it alive, no matter how you release the pointer of the objects.

Clo answered 29/8, 2012 at 10:27 Comment(2)
dear Down-voters! I would have been honoured to get some feedback about why your hands were shaking above the down-voter button, because – you believed or not – I'm not a mind reader to figure out it. thank you!Clo
I'm not sure at all how you meant that: "You show an abuse of self and ...", could you elaborate please? the good demonstration is showing the difference between bypassing and calling the same setter inside the setter, which'd cause infinite recursive loop and it crashes when the stack is overflowed – therefore the final approach is avoiding causing infinite loops in runtime.Clo
V
9

I think it helps to consider how properties are (or might be) implemented by the compiler.

When you write self.users = array; the compiler translates this to [self setUsers:array]; When you write array = self.users; the compiler translates this to array = [self users];

@synthesize adds an ivar to your object (unless you added it yourself), and implements the -users and -setUsers: accessor methods for you (unless you provide your own)

If you're using ARC, -setUsers: will look something like:

- (void)setUsers:(NSArray *)users
{
    _users = users; // ARC takes care of retaining and release the _users ivar
}

If you're using MRC (i.e. ARC is not enabled), -setUsers: will look something like*:

- (void)setUsers:(NSArray *)users
{
    [users retain];
    [_users release];
    _users = users;
}

* - Note that this is a simplified, nonatomic implementation of -setUsers:

Vankirk answered 29/8, 2012 at 10:50 Comment(1)
The only answer on this topic that talks about the difference from a reference counting perspective with such elegance. Excellent.Fantasize
N
2

Yes, that's pretty much correct. A couple of minor points:

iOS doesn't automatically release an object just because you use dot notation. It releases an object when the property is declared as copy or retain (or strong in ARC). If, for example, you are using non-ARC code and the property is declared as assign, it won't release the object.

With the latest version of the developer toolchain (Xcode 4.4+), you no longer have to manually synthesise properties - they are automatically synthesised (with the leading underscore).

Narrows answered 29/8, 2012 at 11:49 Comment(2)
Thanks Jim. I tried Xcode 4.4 with iOS 6 and yes it doesn't require synthesising properties but would that App work on lower version of iOS?Sapindaceous
Yes - from the official documentation: The default @synthesize feature requires no special SDK or runtime support. Questions like that, you should read the documentation.Narrows

© 2022 - 2024 — McMap. All rights reserved.