9

This has been asked a lot, but this question is to get examples of when you would use each of these methods. Please use examples other than the setter and getter infinite loop

example.

.h -
@property(nonatomic, strong)NSMutableArray* mutArray
.m -
@synthesize mutArray= _mutArray;

1) would I want:
_mutArray = [[NSMutableArray alloc] init];
OR
self.mutArray=[[NSMutableArray alloc] init];
Why would I do each of them, and what is the difference?!

2) If I want to add an object to it...
[_mutArray addObject:object];
OR
[self.mutArray addobject:object];

and why?!

Thanks so much!

iPatel
  • 46,010
  • 16
  • 115
  • 137
jgvb
  • 304
  • 5
  • 16

3 Answers3

13

You should only deal with your ivars in init and dealloc or where absolutely required by an implementation detail (such as inside of the accessor itself, or where you actually require a memory address). Other than in those places, you should always use the accessor, which means [self foo] rather than _foo.

self.foo is just syntactic sugar around the actual call, which is [self foo]. It is important to understand that self.foo is a standard ObjC message-send, and means exactly the same thing as [self foo]. By convention, you should only use dot-syntax when referring to properties.

Pre-ARC, direct use of ivars was the #1 cause of crashes in my experience. The likelihood of you screwing up when assigning directly to an ivar without ARC quickly approaches 100% over the scope of the program.

Since ARC, I still argue that you should always use accessors (with the exceptions given above), but the reasons are more subtle. The main reason for it is that an accessor may be customized, either in the current class, in a subclass, or via KVO (which happens outside your code entirely). If you directly access the ivar, then you will bypass this. For example, say the property is lazily-created (which is pretty common). Then if you use the ivar before it's created, you'll get subtle bugs. So you have to remember, for that property, to always use the accessor. Similarly, you might call setNeedsDisplay or post a notification, or the like.

If you have a simple rule that says "I will always use accessors" then it's easy to look at the code and know it's right. In the few cases you need to circumvent the accessor, the _ says "hey, pay attention here, I'm doing something weird."

If you have a rule "I will use accessors for properties that need it, but not for ones that don't" then it's almost impossible to look at the code and know whether it's correct. Did the previous developer use the ivar because it was required or just because he felt like it? Can you change it or not? It's very hard to know.

So even post-ARC, using accessors consistently is good defensive programming and I highly recommend it.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Well that's super conflicting with Ragnar's answer! What do you think about the extra retain added by going through the setter? And also the fact that other people might be working with the code and changing the setters/getters leading to unexpected results? – jgvb Mar 26 '13 at 18:46
  • The "extra" retain is not "extra." It is the required retain that you must apply, and the accessor is the correct place to do this (this only applies to pre-ARC, but failing to apply that retain correctly is the major cause of crashes I mentioned). You want to use accessors exactly *because* other people may be working on the code, and there is no way to ensure they all know and always follow "when you change this ivar, you also have to..." The correct way to document that custom requirement is through the accessor. – Rob Napier Mar 26 '13 at 18:53
  • Occasionally this will lead to surprising results (recalculating something too often for instance), but those side-effects are almost always in my experience much easier to debug than the fact that you didn't know you had to call `setNeedsDisplay` after setting the ivar. That leads to things that "kind of work except when they don't" which are extremely hard to debug. Running an accessor when you didn't know it would happen shows up in the stack trace. Failing to run an accessor you didn't know you needed to run.... that's hard to find. – Rob Napier Mar 26 '13 at 18:56
  • So just to clarify, in the addobject example in my question, those 2 will do the same exact thing, unless the getter/setter is modified? Which is actually called in [self.arr addobject:object];, The getter or setter? – jgvb Mar 26 '13 at 20:27
  • They will do nearly the same thing. The second one will not call `[self mutArray]`, the first won't. A default getter actually has atomic wrappers in it, which is different. Your comment example can be rewritten `[[self arr] addObject:object]`. (Which is exactly how we used to write it before dot-syntax.) – Rob Napier Mar 27 '13 at 12:12
0

_mutArray is the iVar, self.mutArray accesses the property through getters and setters which are created for you when you @synthesize the property. You can overwrite these getters and setters to due custom stuff. In your example, you're property is set to strong, which adds a retain to your property. So self.mutarray = [[NSMutableArray alloc] init]; would do something like this (unless you over-write the property's setter):

-(void)setMutarray:(NSMutableArray*)_mutArray{
    if(_mutArray != mutArray){
        [mutArray release];
        mutArray = nil;
        mutArray = [_mutArray retain];
    }
}

For adding objects to an array you would want to just access the iVar, not the property unless you are doing something custom in the getter. For example you're getter might look like this:

-(NSMutableArray*)mutArray{
    if(!mutArray){
        self.mutArray = [[[NSMutableArray alloc] init] autorelease];
    }
    return mutArray;
}

in this way you could ensure that you always had a real array to add objects to. If this is the case you would want to use [self.mutArray addObject:object];

So, unless you want to do something custom in the getter or setter you just want to access the iVar.

Kelly Bennett
  • 725
  • 5
  • 27
  • Why do I not want to go through the setter and getter unless I customize? – jgvb Mar 26 '13 at 18:28
  • You don't want to go through the setter because it will add a retain. Also, if other people are working with the code, they might be doing something in the getter or setter that you are not accounting for. – Kelly Bennett Mar 26 '13 at 18:31
  • I'm not an expert, but I respectfully disagree. In non-ARC environments, you *need* that retain - it's not extra. In ARC, it doesn't matter. Another thing to consider: if you're not using an accessor, you'll have to ALWAYS check that your iVar is instantiated before using it (and alloc/init if it's not). Without even getting into the KVO stuff, this presents a strong case for always using setters/getters. – emma ray May 21 '14 at 15:42
0

self Is keyword like this keyword in JAVA.

It access to current object and also It is a pointer to an object.

for more info about self read this tutorial

_ObjeName is called iVar in Objective c

Instance variables declared in the implementation are implicitly hidden (effectively private) and the visibility cannot be changed - @public, @protected and @private do not produce compiler errors (with the current Clang at least) but are ignored.

For Example :

Different between

1) NSString *someString = _name;

2) NSString * someString = self.name;

Assume you have in your .m file this line (and don't have any overriden methods to direct access to _name)

@synthesize name = _name;

It mean that property name (self.name) will use variable _name when you try to access it. In this case self.name is equal to _name


But if you have dynamic property for name, something like this :

-(NSString)name{
    return @"1234";
}

then there is a difference. self.name will always return 1234, but _name can be not equal to this value.

Example:

_name = @"555";
NSLog(_name);
NSLog(self.name);

Result:

2012-02-09 14:27:49.931 ExampleApp[803:207] 555
2012-02-09 14:27:49.933 ExampleApp[803:207] 1234

Above Example I Got From this Question.

Community
  • 1
  • 1
iPatel
  • 46,010
  • 16
  • 115
  • 137
  • 2
    Saying that 'self' is like 'this' is extremely confusing to new developers. `this` can be implied on Java. `self` is never implied in ObjC. This leads to much confusion when former Java developers think that `_name` and `self.name` ever mean exactly the same thing. They are never identical, they will always generate different assembler code, they just may happen to return the same result. – Rob Napier Mar 26 '13 at 18:49
  • @RobNapier +1 . I have come from Java background to ObjC and was also making the comparison with `this` and `self` which although related, are a different thing. – Petar Mar 26 '13 at 19:45