What's the difference between self.propertyName vs. propertyName? - iphone

The title says everything!
In Objective-C, what's the difference between self.propertyName vs. propertyName?

self.propertyName is sending the object a message, asking it for the value of propertyName, which means it may go through a getter/setter, etc. propertyName is directly accessing the ivar, bypassing any getter/setter. Here's an article going into it in rather more detail.

self.propertyName increse the retain count by one if you have specified the propertyName as retain in property declaration
propertyName will not increase the retain count an could lead to the crash of application.
e. g. ,
#property (nonatomic,retain) NSString* propertyName;
lets say you have nameProperty NSString object.
Below increase the retain count by 1 and you could use self.propertyName and call release.
self.propertyName = nameProperty;
[nameProperty release];
Below does'nt increase the retain count so if you use propertyName in your application it will result in crashing of your application.
propertyName = nameProperty;
[nameProperty release];
Any further use of propertyName will result in crash.

self. runs through your likely synthesized accessor methods if you are using properties
ie self.propertyName = newName is the same as [self setPropertyName:newName]
This becomes important for memory management as propertyName = newName would cause you to loose reference to the previous contents of propertyName

If you call self, you can be sure you're calling the class/object that owns the property.
You may find this useful too:
Assigning to self in Objective-C

dot notation is turned into a method call by the compiler. This means that there is extra work at run time for executing this method call, like copying something from and to the stack memory and executing a jump in machine code.
the instance variable by itself is faster because it is essentially just a memory address or scalar value (like int).
One would prefer the self.something notation when you want or need an extra layer to do something. Like retain an object that is passed in or lazily instantiate an object on the first time you need it.

Setting the value of the property does just that - it sets the value of the property directly without going through any accessors or synthesized accessors.
By calling the accessor through self you are going through the accessors. For properties that have been declared with retain or copy it will retain or copy the value that is passed in. For non objecte properties, the usual declaration is assign which means that there is no memory management applied to those iVars.
You see both types of calls - but it is preferred to use the direct method in initialisers and the dealloc method, because calls to self are discouraged in these methods.
If you have declared and synthesized the property, the call to self also generates the KVO notifications for changes in that variable. This saves you having to write the willChangeValueForKey: and didChangeValueForKey: methods.

Related

Need to retain, and synthesize NSStrings?

I'm a bit confused as to whether NSStrings should ever be retained and synthesized. I have a NSString value as an instance variable, and am retaining and synthesizing it. But I am assigning it different values such as:
self.value = #"VALUE";
....
self.value = #"DIFFERENT_VALUE";
I'm not actually calling alloc anytime. Do I need to retain and synthesize this variable then?
You can think of on-the-fly strings as autoreleased in terms of how you use them, although in reality they will probably stay around as fixed values... because you are using the accessors they will automatically get copied or retained (however you marked the accessor) and so you do need to release them in dealloc.
As for the need to #synthesize, remember all that is doing for you is actually creating the get/set methods that take the variable and place it in your iVar. So not matter what you either need to #synethsize a property OR create the get/methods yourself - usually far better just to use #sythesize.
You should as you'll never know how you are going to change the use of the code in the future. Change the code to use dynamically created strings, and it will break if don't follow the rules.
Also note that the best practice for NSString is to set it to copy instead of retain. The reason is simple, this prevents the string from being changed under your feet.
See NSString property: copy or retain? for more details.
If you have never alloc'ed them, you usually don't need to retain, but if they are instance variables in your objects, they are probably marked as retain or copy so at your object's dealloc method you should release these objects if there is a value on it.

Assigning ivars using self keyword in an object's init method

I've read that it's bad to use self.ivar = (convenience method) in and object's 'init' method, as this messes with inheritance.
However, if you know you're not going to subclass your object, is it ok to use the self keyword assignment?
i.e. self.iVar = [Object objectConvenienceMethod];
The reason I ask is this. I create a new object with its own init method, and in that method, I perform various initial assignments. Since I don't use the self keyword, I assign them directly to the iVars, and therefore use the alloc methods rather than the convenience methods. I.e.
iVar = [[Object alloc] init];
Or if I use a convenience method, I retain it. I.e.
iVar = [[Object convenienceMethod]retain]
But... when I run my program with the memory leak tool on, all of these assignments are identified as memory leaks.
If I can use the self keyword plus a convenience method instead of alloc-init, then this would avoid the problem.
If I choose to use the alloc-init approach though, where am I supposed to release the iVars?? Just in dealloc?
Thanks for your help :)
Michael
No, because it isn't only subclass behavior you need to take into account — superclass implementations and even the behavior of code generated by the framework (e.g. synthesized accessors and the black magic used to implement KVO) can also cause trouble. It will probably be OK, but that's still a significant chance of being not-OK. All in all, it's best just to follow Apple's recommendation and assign directly.
Assigning to ivars in init shouldn't be reported as leaks in a properly functioning program. If you're seeing that, there's some other problem that you need to address. Try reducing the problem to a minimal case that we can try out and ask about that — then we can tell what's wrong.
If you alloc or retain them in your class's init method, you should release them in the corresponding dealloc method.
I am thinking your "enclosing" class is not being released, and hence its dealloc method is not being called resulting in your iVars not being released.

retain with objective-c

I have a question about a retain and a NSString, if I have a method who a return a NSString, and I put the return NSString in a nsstring variable, I must do a retain or not?
NSString *myString = #"";
myString = [self methodWhoReturnString]; // I must do this?
myString = [[self methodWhoReturnString]retain]; // Or I must do this?
The Apple Developer Documentation on Memory Management explains the scenarios where you retain/release objects.
Simply put, if you want the string to stick around, you need to retain it until you're finished with it. If that is just the scope of the current function, you can get away without retaining it as if the string is already autorelease'd (likely) it won't get released until your function finishes and the current AutoReleasePool is purged.
Bear in mind that an NSString * could actually be pointing to an NSMutableString *. If it matters to you if the string is changed by some other function without you realizing, be sure to copy it: NSString * myCopyOfString = [mystring copy];
If the string is set to autorelease, which it most likely is, then yes you will need to retain it somehow. I would suggest doing this though:
myString = [[self methodWhoReturnString] copy];
this ensures you have retained the data in the string not just a reference to a string that might still be controlled elsewhere. Be sure you release your copy later!
Usually, methodWhoReturnString would return an autoreleased string, which means you should retain it if you want to keep it around.
So, if methodWhoReturnString is your method, I believe that to keep with convention you should return [stringToReturn autorelease]; from that method, and then retain it if you want to keep it.
You use retain if you're going to be using myString at a later point in time (i.e. after the current method has returned) to prevent it being autoreleased.
You don't need to use retain if it's just a temporary variable used within the current method, since in that case you do want it to be autoreleased.
One special case is properties. If you call self.blah = foo, you don't need to retain foo, since the setBlah: method should do it for you.
(there's a whole load of other complexities and edge cases, but this is a good rule of thumb to get you started on understanding what to do)
Given the code you provided, you shouldn't call -retain. In your example, the return value of a method that returns an instance of NSString is assigned to myString, an automatic local variable. If the assignment had been made to an instance variable or a static variable, you would want to call either retain or copy to guarantee that the reference remains valid beyond the end of the local scope.
In this case though, the reference to the NSString instance is stored in a variable that will be destroyed automatically at the end of the local scope, so your code needn't concern itself with the object's lifetime.
Any method that has alloc, new or copy in it automatically retains and infers that you have ownership of the object. All others shouldn't. It would be helpful if you had more context though. If we are in a contained method where this string is used briefly, then you probably don't need to retain. If it is going to be used for a while, you might want to use the #synthesize syntax to make it a property of the class you are in. When you use #property and #synthesize and call something like self.myProperty = something it will automatically retain.

Different between self.myIvar and myIvar?

What's the difference between referring to an instance variable in an objective-c class as this:
self.myIvar
and
myIvar
if it's been declared as a property in the header and synthesized?
If you refer to self.myVar, it will use the #property declared in your header file.
For example
#property(nonatomic, retain) Class *myClass;
If you have
myClass = [ [ Class alloc ] init .... ];
Retain Count will be 1
But if you use
self.myClass = [ [ Class alloc ] init .... ];
Retain Count will be 2 because of the retain property.
It's the same if you set setter || getter method in the #property.
What's the difference between referring to an instance variable in an objective-c class as this:
self.myIvar
and
myIvar
if it's been declared as a property in the header …
Simple: The former does not refer to an instance variable.
It refers to a property named myIvar. Likewise, the latter refers to an instance variable and not a property.
The property is, of course, misnamed, because a property and an instance variable do not necessarily have anything to do with each other, and indeed a property does not even need to be backed by an instance variable.
Attempting to access self.myIvar is exactly the same as sending self a getter message for the property. That is, these two statements:
foo = self.myIvar;
foo = [self myIvar];
are exactly the same.
Likewise, attempting to assign to self.myIvar is exactly the same as sending self a setter message. These two statements:
self.myIvar = foo;
[self setMyIvar:foo];
are exactly the same.
By comparison, referring to the instance variable myIvar (no self.):
foo = myIvar;
myIvar = foo;
is exactly that: accessing a variable; nothing more.
This means a lot.
The accessors, particularly the setter, tend to have side effects. For example, if the property is declared as retain, a synthesized setter for it will release the old value of the property and retain the new value. Likewise, if the property is declared as copy, a synthesized setter will release the old value and make a copy of the new one.
Since an assignment to a property:
self.myProperty = foo;
is an accessor message, that “assignment” will cause the old value to be released and the new value to be retained/copied.
An assignment to a variable:
myIvar = foo;
being nothing more than an assignment to a variable, will not do that. If you owned the old value of myIvar, you just leaked it, and if you don't already own the new value, you still don't own it, which means it will probably die while you're still holding onto it, leading to a crash later. (See the Memory Management Programming Guide.)
Despite the two looking similar, they are very, very different.
As a general rule, you should use your properties everywhere except init methods and the dealloc method, and directly access the instance variables (where you have instance variables) in those methods. (Again, accessors may have side effects; you're likely to not want those side effects in a half-initialized or half-deallocated object.)
… and synthesized?
That doesn't matter. #synthesize is just one of three ways of telling the compiler how the property's accessors are implemented:
#synthesize: Compiler, you implement them.
#dynamic: Don't worry about it, compiler; my superclass will dynamically supply the accessors at run time. (Most common in subclasses of NSManagedObject.)
- (Foo *) myProperty { … } / - (void) setMyProperty:(Foo *) newFoo { … }: Here are my implementations of the accessors.
Failing to do one or more of those things for a property will get you a warning from the compiler and probably some run-time exceptions, because you never actually stated an implementation for the accessors that (by declaring a #property) you declared the instances would have.
The difference is that ivar is just a variable pointing to a location in memory, whereas self.ivar calls the setter (in the case of self.ivar = x) and getter (for x = self.ivar) methods. IE, under the hood, the self.ivar in these statements gets translated into [self setIvar:value] and [self getIvar] respectively . These methods can then handle things like retain/release and any class-specific behaviour on your behalf, and in fact do so by referencing ivar directly. The #synthesize keyword automatically generates these getter and setter methods for you to cut down on boilerplate code.
So, ivar is a location in memory where your object can store something, and self.ivar wraps class methods around that location in memory to manage access to it. Note that when initializing an object it is usually preferable to set the ivars directly to avoid possible strange behaviour with not-quite-fully-formed objects.
Without the self. part you'll be accessing/assigning the actual data member of the class, without going through the getter/setter generated by #synthesize (or you can write your own getter/setter if you need something more fancy than the default behavior).
Note that in those custom accessors you'd pretty much have to omit the self. part to avoid endless recursion, e.g. if you have a string property called s, a setter could be (this is similar to what is generated when you do #synthesize, by the way):
-(void)setS:(NSString *)newVal
{
if(newVal == s) return;
[s release];
s = [newVal retain]; //if you use self.s here, setS will be called again
}
self.ivar
calls a property method that you can later change or add to, and that might do some memory management as well. For instance, you could make setting self.ivar also change ivar2, increment ivar3, bounds check ivar4, send a message to object5, release object6, play sound7, etc.
ivar
just reads or writes some number of bits in memory.

Calling property's setter method with nil value

Consider I have a property named sampleObject.
In dealloc method, which should be the best way to manage memory?
Option 1:
self.sampleObject = nil; //This will release the sampleObject and set it to nil
This is equivalent to
[sampleObject release];
sampleObject = nil;
Option 2:
Explicitly releasing an object and setting it to nil
[sampleObject release];
sampleObject = nil;
In my opinion, both would achieve the same results? Please Share your views.
Regards,
Krishnan
In the 'dealloc' method you should 'release' the ivar directly and set it to nil.
You do so directly because that avoids executing any custom setter code that may exist in a subclass.
The setting to nil isn't strictly necessary, but it costs virtually nothing to do and you'll be happy you did so during debugging in that it eliminates a dangling pointer.
in a dealloc method, the class is never used again so setting retained resources/properties to nil is just not required. Sending release is the best option and avoids unnecessary code.
Going through the property setter does have a small overhead over directly sending the release message. Thus, for synthesized properties, it's better to send release.
Of course, there are cases where you have to call the property setter, if the setter logic is more complex (for example, the property is backed by multiple variables and the setter decomposes the value and cleans up the old one). This is not as common scenario, though.
And since you are deallocating your object, there's no need to set the backing variable explicitly to nil after you release it.