This question already has an answer here:
What's the difference between _variable & self.variable in Objective-C? [duplicate]
(1 answer)
Closed 9 years ago.
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?
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
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.
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.
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/
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
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"
Related
Worrying about duplicates but can not seem to find and answer I can understand in any of the other posts, I just have to ask:
When I have in my .h:
#interface SecondViewController : UIViewController{
NSString *changeName;
}
#property (readwrite, retain) NSString *changeName;
then in my .m
#synthesize changeName;
-(IBAction)changeButton:(id)sender{
changeName = #"changed";
}
Is it the synthesized property or the instance variable that get changed when I press "changeButton" ?
You (and it seems some of the others that answered) are confusing properties with actual variables.
The way properties work is, they create METHODS (called setter and getter) that set or get/return ivars. And the do notation (self.string) actually INVOKES these methods. So a property can't be CHANGED, only the declared iVar is.
When you declare a property like so:
#property (nonatomic, retain) NSString *string;
And #synthesize it the following happens:
An iVar called string (of type NString*) is created
(if you do
#synthesize string = whateverYouWant
the iVar created
is called whateverYouWant - a convention is to name the iVars
the same as the property with preceding underscore (_string))
an accessor method is created like this
-(NSString*) string;
a setter is created like this
-(void) setString: (NSString*) newString;
Now what self.xxxx does is, it actually sends the message xxxx to self
(like [self xxxx]).
It works with ANY method, not just properties, though it should only
Be used with properties.
So when you do self.string = #"hello" it actually comes down to
[self setString: #"hello"];
(Note that the compiler actually knows you are trying to set and so the
setString message is sent instead of just string. If you accessed self.string
it would send [self string])
Thus you don't SET a property, you invoke the (synthesized) setter method that in
itself sets the iVar.
Accessing your iVar directly is ok, if you know what your doing.
Just calling
string = #"something else";
Will produce leaking code, since no memory management is done.
The synthesized accessors and setters actually do this for you, depending
on how you defined th property (retain,copy,assign).
Because the setter (for a retained property) doesn't just do
IVar = newValue
If you declared a retained property it actually looks something like this:
-(void) setString: (NSString*) newString {
if (string) [string release];
string = [newString retain];
}
So the property synthesize takes a bit of work off your hands.
EDIT
Since it still doesn't seem clear, the property that is declared is not to be thought
of like a variable. In the above example, when using
#synthesize string = _string;
there IS NO variable called "string". It's just the way you access the method structures
that set the iVar _string through the setter methods. Since string is no variable/object pointer, you cannot send messages to it ([string doSomething] won't work).
When you just synthesize the property using #synthesize string; the generated iVar gets
the same name as the property.
Calling [string doSomething] will then work, but it has nothing to do with the property. The "string" refers to the iVar. Hence th convention to name the iVars underscored, so
you don't accidentally access the iVar when you meant to use the getter/setter.
Both. Property uses instance variable as its storage. In your code you change the instance variable, but if you access the property (via self.changeName) you'd get the same value as instance variable.
Usually to distinguish between ivars and properties people use _ prefix for ivars. And then synthesizes properties like this:
#synthesize myProperty=_myProperty;
well, the var
it's always the var
in your case the property methods aren't used at all.
now, consider this case:
self.changeName = #"changed";
this way you are using the property, but that just means that you are using the methods "magically" created for you by the compiler, the setter and getter methods, where you, again, change the var (property doesn't exist, in reality, it's just a way to create the setter and getter methods for you)
I have a NSString called fontType
and I am trying to have a custom setter for it:
- (void) setFontType:(NSString *) fType
{
if (self.fontType != fType){
[fontType release];
self.fontType = [fType retain];
//some more custom code
}
}
Is there any issue with this?
A few things that stand out for me:
do not use self. inside of custom accessors. access the variable directly
it's better use copy semantics for properties of a type that has a
mutable subtype
be careful with whatever is // some more custom code
My personal style preferences are like so:
-(void)setFontType:(NSString *)fontType_ {
if (fontType == fontType_) return; // get out quick, flatten the code
[fontType release];
fontType = [fontType_ copy];
// some more code
}
Cocoa with Love has a good article on this topic. It's worth a read.
When you do self.fontType = newFontType, you are doing [self setFontType:newFontType] (just with a different syntax), this means you are calling the method inside itself.
This is called recursion, but in this case, you don't have a base case in which the method will stop calling itself, so my guess is that this method will call itself until the app crashes. In short, recursion is not something you want here.
Just replace self.fontType = [fType retain] with fontType = [fType retain] (Assuming the var linked to the fontType property is called fontType as well).
PS. At the end of the question you asked
Is there any issue with this?
If you didn't try this, then you shouldn't even be asking that here on StackOverflow, and if you did try it, then you should have realized that this method didn't work, so that last line is pretty meaningless. Just saying.
I am looking for a shorthand way of setting my properties directly to an NSMutableDictionary that is a instance variable. ie:
KVCModle.h:
#interface KVModel : NSObject {
NSMutableDictionary * data;
}
#property(nonatomic,assign)NSString * string1;
#property(nonatomic,assign)NSString * string2;
#end
KVCModel.m
#import "KVModel.h"
#implementation KVModel
-(id)init
{
self = [super init];
if(self)
{
data = [[NSMutableDictionary alloc] init];
}
return self;
}
-(NSString *)string1
{
return [data objectForKey:#"string1"];
}
-(NSString *)string2
{
return [data objectForKey:#"string2"];
}
-(void)setString1:(NSString *)_string1
{
[data setObject:_string1 forKey:#"string1"];
}
-(void)setString2:(NSString *)_string2
{
[data setObject:_string2 forKey:#"string2"];
}
-(void)dealloc
{
[data release];
[super dealloc];
}
#end
I have tried to override setValue:ForKey: and valueForKey:, but those aren't called, they allow you to directly set properties without using the property syntax.
I have made preprocessor macros to make this work in the past, but I am not interested in typing at all, and would like to avoid as much of it as I can in the future. Is there a way to make this work that I am not familiar with?
I have thought about using NSManagedObject, but I am not sure if I can get what I want out of that.
EDIT:
source
If you're trying to access the properties with code like foo = obj.foo and obj.foo = foo, that's why it doesn't work.
Property-access syntax is synonymous with message syntax; the former is exactly the same as foo = [obj foo], and the latter is exactly the same as [obj setFoo:foo]. There is no KVC code to intercept. Properties are at the language level; KVC is at the framework level.
You'll need to intercept the accessor messages instead. Consider implementing the resolveInstanceMethod: class method, in which you “resolve” the selector by adding a method implementation to the class using the Objective-C runtime API. You can add the same implementation(s) for many different selectors.
For your purpose, have a function or method that examines the selector (using NSStringForSelector and regular NSString-examining techniques) and returns two facts: (1) the property name, and (2) whether it's a getter (foo, isFoo) or setter (setFoo:). Then, have two more methods, one a dynamic getter and the other a dynamic setter. When the selector names a getter, add it with your dynamic-getter method; when the selector names a setter, add it with your dynamic-setter method.
So how do the dynamic-getter and -setter methods work? They'll need to know what property to dynamically get and set, but they also need to take no arguments (getter) or one argument (setter, which takes the value), in order to match the original property-access message. You might be wondering how these generic implementations can know what property to get or set. The answer is: It's in the selector! The selector used to send the message is passed to the implementation as the hidden argument _cmd, so examine that selector the same way as before to extract the name of the property you should dynamically get or set. Then, the dynamic getter should send [data objectForKey:keyExtractedFromSelector] and the dynamic setter should send [data setObject:newValue forKey:keyExtractedFromSelector].
Two caveats:
You may still get complaints from the compiler when you use the property-access syntax to access a “property” that you have not declared in the class's #interface. This is normal and intentional; you're really only supposed to use property-access syntax to access known formal properties. What you're doing, while I found it fun to solve, is technically an abuse of the property-access syntax.
This will only work for object values. KVC does the boxing and unboxing for primitive values, such as integers; since KVC is not involved, no free boxing and unboxing. If you have declared formal properties (see 1), you'll need to introspect them using the Objective-C runtime API, and do the boxing and unboxing yourself with your findings.
This piqued my curiosity, so I went ahead and used Peter Hosey's suggestion of overriding +resolveInstanceMethod: to generate the getters and setters. I posted the resulting object (DDDynamicStorageObject) to a github repository:
https://github.com/davedelong/Demos
What you basically want is your own implementation of the NSManagedObject machinery. I have done something similar. Look here: https://gist.github.com/954035 HTH
(Updated the code to remove the dependency on the non-existant NSString+Utilities.h)
(Added missing ReleaseAndZero() macro)
For the love of all that is sacred - do not use an NSDictionary as a place to stuff every conceivable property of a model object. Ivars are easier to debug, and much much clearer to other developers (including your future self).
If you want to use a dictionary, use a dictionary and some statically defined keys - but if you want a model object, use some ivars
I come to the same problem today just like you. So I find your question posted here.
The answers above used the +resolveInstanceMethod: is a little bit hard for me. :)
My understanding is that as long as we setup the property, we would have getter and setter method, so I use the setter method to implement it.
BDLink.h
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *displayName;
#property (nonatomic, strong) NSString *linkURI;
BDLink.m
- (id)initWithLinkInfoDictionary:(NSDictionary *)linkInfoDict {
for (NSString *key in linkInfoDict) {
const char *rawName = [key UTF8String];
NSString *setMethodString = [NSString stringWithFormat:#"set%c%s:", toupper(rawName[0]), (rawName+1)];
SEL setMethod = NSSelectorFromString(setMethodString);
if ([self respondsToSelector:setMethod]) {
[self performSelector:setMethod withObject:linkInfoDict[key]];
}
}
return self;
}
Hope it would be helpful. My first answer, :)
For the following two lines in an obj-c class:
self.instanceVar = X
instanceVar = X
Is the only difference that the 'self' version calls the synthesized 'setter', whereas the latter simply sets the instanceVar and doesn't go through the setter?
Thanks
Yes. The implication of this is that the synthesized getter will wrap additional code depending on how the property is specified - so use of assign / retain / copy along with nonatomic / atomic change the behaviour.
Imagine the following:
#property( retain ) NSString * myprop;
If you set it by self.myprop, the NSString instance will be retained.
If you set directly the instance variable, this will not be the case.
So always use the self., unless you're absolutely sure...
This is an excellent question and understanding the difference between setting a variable through its accessor rather than directly assigning it is very important.
Here's what happens: when you declare a #property (nonatomic, retain) NSString *variable in the header, you add a property to your object. Simple enough. Calling #synthesize does the following thing: it generates two methods in your class, setVariable: and getVariable. Of course, if you name your property "name", the methods will be setName: and getName.
Now, it is important for you to understand what happens in the setVariable: method. The method is declared something like this:
- (void)setVariable:(NSString *)theVariable {
if (variable != nil) {
[variable release];
}
// variable is the class member,
// theVariable is the object that was sent by the method parameter
variable = [theVariable retain];
}
When you call self.variable = #"test"; you will actually call [self setVariable:#"test"] which is exactly the method that was generated by the #synthesize call!
When you call variable = #"test"; you do just that - you assign a string to a variable, without retaining it or anything.
If you were to call self.variable = nil the current value of the variable would be released and variable will be assigned to nil, but if you were to call variable = nil you would just ditch the reference to the previously assigned value (object). Therefore, if you would be calling
self.variable = #"test";
// wrong, do not do this in this case
variable = nil;
you would be be generating a memory leak because the #"test" object that was assigned to variable and retained through its accessor is never going to be released. Why's that? Because the setter (setVariable:) never gets called to know to release the previously held value.
For the sake of example, here's what getVariable looks like:
- (void)getVariable {
// variable is the class member
return variable;
}
Let me know if you have further questions.
Yes. self.instanceVar accesses the value through the property.
Although it is not necessarily the synthesized property. You can write your own get and set methods that can be called.
I'm trying to understand how strategies some folks use to distinguish instance vars vs. properties. A common pattern is the following:
#interface MyClass : NSObject {
NSString *_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#end
#implementation MyClass
#synthesize myVar = _myVar;
Now, I thought the entire premise behind this strategy is so that one can easily distinguish the difference between an ivar and property. So, if I want to use the memory management inherited by a synthesized property, I'd use something such as:
myVar = #"Foo";
The other way would be referencing it via self.[ivar/property here].
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Thanks.
Properties are just setters and getters for ivars and should (almost) always be used instead of direct access.
#interface APerson : NSObject {
// NSString *_name; // necessary for legacy runtime
}
#property(readwrite) NSString *name;
#end
#implementation APerson
#synthesize name; // use name = _name for legacy runtime
#end
#synthesize creates in this case those two methods (not 100% accurate):
- (NSString *)name {
return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
[value retain];
[_name release];
_name = value;
}
It's easy now to distinguish between ivars and getters/setters. The accessors have got the self. prefix. You shouldn't access the variables directly anyway.
Your sample code doesn't work as it should be:
_myVar = some_other_object; // _myVar is the ivar, not myVar.
self.myVar = some_other_object; // works too, uses the accessors
A synthesized property named prop is actually represented by two methods prop (returning the current value of the property) and setProp: (setting a new value for prop).
The self.prop syntax is syntactic sugar for calling one of these accessors. In your example, you can do any one of the following to set the property myVar:
self.myVar = #"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: #"foo"]; // handle retain/release
_myVar = #"Foo"; // does not release old object and does not retain the new object
To access properties, use self.propname. To access instance variables use just the instance variable's name.
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Because the variable myVar is undeclared.
That statement uses the syntax to access a variable, be it an instance variable or some other kind. As rincewind told you, to access a property, you must use either the property-access syntax (self.myVar = someOtherObject) or an explicit message to the accessor method ([self setMyVar:someOtherObject]).
Otherwise, you're attempting to access a variable, and since you don't have a variable named myVar, you're attempting to access a variable that doesn't exist.
In general, I name my properties the same as my instance variables; this is the default assumption that the #property syntax makes. If you find you're fighting the defaults, you're doing it wrong (or your framework sux, which is not the case for Cocoa/Cocoa-touch in my opinion).
The compiler error you're getting is because property use always has to have an object reference, even inside your own class implementation:
self.stuff = #"foo"; // property setter
[stuff release]; // instance variable
stuff = #"bar"; // instance variable
return self.stuff; // property getter
I know that many Cocoa programmers disagree, but I think it's bad practice to use properties inside your class implementation. I'd rather see something like this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
[stuff release];
stuff = [theStuff copy];
// do something else
}
than this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
self.stuff = theStuff;
// do something else
}
I prefer to do memory management as explicitly as possible. But even if you disagree, using the self.stuff form will clue in any experienced Objective-C programmer that you're calling a property rather than accessing an instance variable. It's a subtle point that's easy for beginners to gloss over, but after you've worked with Objective-C 2.0 for a while, it's pretty clear.
Don,
According to the "rules", you should call Release for every Copy, Alloc, and Retain. So why are you calling Release on stuff? Is this assuming it was created using Alloc, Copy, or Retain?
This brings up another question: Is it harmful to call Release on a reference to an object if it's already been released?
Since Apple reserves the _ prefix for itself, and since I prefer to make it more obvious when I am using the setter and when I am using the ivar, I have adopted the practive of using a prefix of i_ on my ivars, so for example:
#interface MyClass : NSObject {
NSString *i_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#synthesize myVar = i_myVar;
i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]
Since it is quite important to know when you are using the setter and when you are using the ivar, I find the explicitly different name is safer.
In your question, it should be:
self.myVar = #"Foo"; // with setter, equivalent to [self setMyVar:#"Foo"]
and
_myVar = some_other_object; // direct ivar access - no memory management!
Remember that you should not use setters/getters in init/dealloc, so you need to do your direct ivar access (and careful memory management) iin those methods.
what's wrong with simply using
#interface MyClass : NSObject
#property NSString *prop;
#end
nonatomic and retain are not required, retain is the default, and atomic/nonatomic isn\t important unless XCode tells you with a warning.
it is NOT necessary to declare the iVar, one will be created for you named _prop, if you really want to use one (i don't see why to be honest)
#synthesize is NOT required.
when (and you should) using ARC you don't have to bother with retain and release either.
keep it simple !
furthermore, if you have a method like this one
- (void)aMethod:(NSString*)string
{
self.prop = string;
// shows very clearly that we are setting the property of our object
_aName = string;
// what is _aName ? the _ is a convention, not a real visual help
}
i would always use properties, more flexible, easier to read.