1

i read a lot of post about this subject, yet i can't understand everything completely. Ok, it's clear that

self.text = @"MyText" will call the accessory method setText (autogenerated)

_text = @"MyText" will still assign the value but will not call the setText

This is clear.

But this can be useful when we are not using ARC beacuse setText will take care of the memory management. But what happen when we are using ARC? Sometimes if i am using _text everything works fine, some other time my application won't work if i wont use "self.text".

So what is the the real difference? There must be something more than memory management.

let's say i have this

@interface MyClass:NSObject { 
  NSMutableString *text; 
}

@property (nonatomic ) NSMutableString *text;

in this case isn't it the same calling

self.text = @"ok" 

or

text = @"ok" ?

what's the difference?

Riccardo
  • 31
  • 5

6 Answers6

7

The underlying instance variable for that property is in fact _text. That is how auto synthesised properties work.

However you should consider using the accessors to set the property (using self. text = instead). See this link for more info on Reason to use ivars vs properties in objective c

Community
  • 1
  • 1
thatzprem
  • 4,697
  • 1
  • 33
  • 41
  • ok it's getting more clear, but what happen if i create an instance called text, and also a property text that i will syntetize like this @syntethize text = text; what happen in that case calling just text or self.text ? will access the same variable? – Riccardo Sep 05 '13 at 09:03
  • Yes. And you can just do `@synthesize text`, `= text` is implicit. Anyway it's a commonly accepted convention the usage of `_` for ivars, so I'd just stick to it. – Gabriele Petronella Sep 05 '13 at 09:09
  • If you want to manually assign it a value, then you use _text = object; Be sure to understand that doing so is not KVC compliant. You will need to inform any observers that the value is about to change. [what is KVC compliance?](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/Overview.html#//apple_ref/doc/uid/20001838-SW1) – thatzprem Sep 05 '13 at 09:12
  • so if in my app im getting error cause i use `text = @"foo"` instaad of `self.text = @"foo" it should be fixed if i just add this? `synthetize foo = foo` ?? – Riccardo Sep 05 '13 at 09:12
  • i just tried to fix my app, but doesn't work... why? – Riccardo Sep 05 '13 at 09:15
4

self.text is syntactic sugar for [self text] (or [self setText:...], if on the left side of the assignment), and is a message; when it is autogenerated ("synthesised"), it will return the value of the connected instance variable. _text is this instance variable.

You can only access an instance variable within the class. You can send a message from anywhere. This distinction is important in case that one day you wish to modify the inner working of the text attribute so that it does not simply return the value of the local variable.

calimarkus
  • 9,955
  • 2
  • 28
  • 48
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • What about if i created an instance var For Text – Riccardo Sep 05 '13 at 08:51
  • You mean `[self text]` and `[self setText:]`. – trojanfoe Sep 05 '13 at 08:53
  • @trojanfoe: I do indeed. Thanks. – Amadan Sep 05 '13 at 08:53
  • actually he was talking about instance vars, not local vars. fixed it. – calimarkus Sep 05 '13 at 08:54
  • What about if i created an instance var For Text `@interface MyClass:NSObject { NSMutableString *text; } @property (nonatomic ) NSMutableString *text;` in this case isn't it the same calling `self.text = @"ok" or text = @"ok" ?` – Riccardo Sep 05 '13 at 08:54
  • 2
    no one time you use the setter (with more logic involved), the other time you just set the value directly. – calimarkus Sep 05 '13 at 08:55
  • but what's the difference? what more logic is involved? ok the retain... but if i use arc it should be the same – Riccardo Sep 05 '13 at 08:56
  • A trivial difference is that `self.text` is marginally slower. It is also safer, as you can change the implementation later. As it stands, they are functionally near-equivalent. It's kind of like only ever paying with cash, or asking your wife to pay for you. She might do the exact same thing you would (pay with cash), but if she gets a credit card she might use that instead. Same result: stuff is paid for. – Amadan Sep 05 '13 at 09:01
  • Apart from the side-effects; in the case of setter/getter there is KVO and KVC, in the case of your wife paying for dinner there is the likelihood she'll want something in return and won't respect you in the morning. – trojanfoe Sep 05 '13 at 09:11
  • please read the update – Riccardo Sep 05 '13 at 09:34
4

the answer is here really Do I need variable and property at the same time?

When you @property you're actually creating methods for accessing and mutating as well as an instance variable.

So when you have @property (nonatomic, strong) NSString *text; you create an iVar _text and two methods:

self.text; //will call -(NSString *)text;
self.text = @"text here"; //is calling -(void)setText:(NSString *)text;

@property is used to strip down boiler plate code, it reduces the number of lines of code required for you to write your classes.

Sure sometimes calling self.text = @"ok" and _text = @"ok" is alright in an ARC environment nowdays, but you don't get the -(NSString *)text; and -(void)setText:(NSString *)text; in your public header file.

Also, its often good practise to call self.text and self.text = or their equivalents [self text] [self setText:] as you might have overridden the text implementations:

-(NSString *)text{
    return [NSString stringWithFormat@"%@.jpg", _text];
}

-(void)setText:(NSString *)text{
    _text = [NSString stringWithFormat:@"DW%@", text];
}

So when you do this:

self.text = @"HelloThere";
NSLog (@"%@", self.text); //This will return DWHelloThere.jpg
NSLog (@"%@", _text); //Will return DWHelloThere
//whereas
_text = @"HelloThere";
NSLog (@"%@", _text); //Will return HelloThere

So @property can save you about 8 lines of code, keeps your own classes nice and tidy, and if need be you can override the accessors and mutators. But because of the latter point its good practise to call self.text and self.text = @"so and so" rather than just accessing the iVar by itself.

Community
  • 1
  • 1
David Wong
  • 10,284
  • 3
  • 39
  • 34
  • wont that do the same? – Riccardo Sep 05 '13 at 08:55
  • this will change something if i customized my setters, but what if i won't customize them? and what happen if when i do the synthetize i specify to use the same name of the instance ? so text instead of _text ? – Riccardo Sep 05 '13 at 09:10
  • Well, if you don't change anything the only other thing I can think of off the top of my head is calling the iVar directly will affect KVO and if someone writes a program around your class with KVO they won't be notified of the changes made while running methods inside your class. – David Wong Sep 05 '13 at 09:16
2

Conceptually, the difference is only that in one case a message is sent to the object or a single ivar is changed in the other. The memory management story is just a necessary house keeping that is handled for you by ARC if you use it.

If you are interested in the moral story, then read Jon Reid's post here: Dot Notation in Objective-C: 100% Pure Evil http://qualitycoding.org/dot-notation/

Side note: Whenever you can, use ARC. It will take care of the retain-release cycle automatically in most cases correctly (accessing self in blocks should be handled with care, though.) If you use ARC there is no difference between the two methods, the retain count will be handled correctly. And as you described, without ARC, you must make sure that after the property setting, the object must be released, while this is not necessary when the ivar is accessed. More on some practices is described in this post: Properties and Memory Management in Objective-C http://www.whilethis.com/2011/04/properties-and-memory-management-in-objective-c/

allprog
  • 16,540
  • 9
  • 56
  • 97
1

the real difference is that:

when you create your instance in your code you have a variable called text. when instead you use the property on text, it will create an iVar called _text.

as you can imagine, calling one or another, will be a big difference since they are 2 totally different variables

stabilocode
  • 168
  • 8
1

self.text = @"Something" accesses to you private variable _text using accessor method [self setText:@"Something"]. The dot notation is just a syntactic sugar. This method can have its own implementation adding extra functionality to just setting value of private variable _text.

_text = @"Something" sets the value to the private variable itself directly.

Also, when setting text property's value outside the class implementation, the accessor [instance setText:@"Something"] is called automatically to set the value of private variable


Let me show you simple example what could be difference. The method implementation is simple just for educational purposes, so it may not make sense in real code :-)

Imagine you want to log a message to the console every time the value of text property changes. You can accomplish this by overriding the accessor method - (void)setText:(NSString *)text like this for example:

- (void)setText:(NSString *)text
{
    //  You can do whatever you want with the input "text" value, validate the value for example
    //  Here we just log the text was changed
    //  In the log message, we still have the old value of the "text" in the private variable "_text"
    //  so we can log it together with the new value
    NSLog(@"Value of \"text\" property changed from \"%@\" to \"%@\"", _text, text);

    //  Set the new value of the private variable
    _text = text;

    //  From here on, the private variable already has new value and the log line above
    //  would give the same values between from and to quotes
    NSLog(@"Value of \"text\" property is now \"%@\"", _text);
}

So when you set the _text directly, none of the log messages above would be performed, because you access the variable directly.

On the other hand, setting using accessor method self.text = @"Something" would cause following to be printed out to the console:

Value of "text" property changed from "(null)" to "Something"
Value of "text" property is now "Something"
Lukas Kukacka
  • 7,604
  • 2
  • 25
  • 50