Releasing a property (Objective-C) - objective-c

I have a #property which is defined like this :
#property (nonatomic, retain) name;
In a function I parse some xml and set the name property.
My question is should I explicitly release previous retained instance before retain a new one ?
For exemple :
myObj.name = [otherObj getName]; // retain count +1
..
myObj.name = [otherObj getName]; // which is a new instance of a name, is the previous name released ?

In a synthesized property setter, the code does something roughly analogous to this (we'll have name be the property name, and _name will be the instance variable to which it refers):
- (void) setName: (NSString *) newValue
{
if ( newValue == _name )
return;
[newValue retain];
[_name release];
_name = newValue;
}
Now, that shows what would happen based on your property declaration above. Depending on the other possible attributes of that property, that function would either use [newValue copy] instead of [newValue retain] (if the 'copy' attribute was specified), or it would all be wrapped in an #synchronized(self) block (if the 'nonatomic' attribute was NOT supplied).
I should also note that since your property refers to an NSString, which implements the NSCopying protocol, you should really be using copy rather than retain, i.e.:
#property (nonatomic, copy) NSString * name;
That will cause the synthesized setter to use -copy instead of -retain, which is safer when you're actually passed an NSMutableString object. An immutable string would ultimately only get retained by the -copy call, while a mutable string would create a new immutable copy. Failing to do that means that the string itself could be changed after it's been passed into the setter, changing the value without your object's knowledge.

If you have synthesized the accessors for your property (with the #synthesize directive), they will take care of releasing the ivar that is backing the property when the property gets reassigned. The only time you might want to explicitly release the ivar is when your object gets deallocated. So, your dealloc method might look like this:
- (void)dealloc {
[name release];
// other cleanup here
[super dealloc];
}

Related

assign NSMutableArray with #property and 'copy' attribute

I'm following an official tutorial Your second iOS App:Storyboard and it told me to declare a property masterBirdSightingList like this(just a specific example and not necessary to know the context) :
#property (nonatomic, copy) NSMutableArray *masterBirdSightingList;
Note that there's an attribute copy. and then synthesize this property :
#synthesize masterBirdSightingList = _masterBirdSightingList;
And next there's one init method which made me confused :
- (void)initializeDefaultDataList {
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
[self addBirdSightingWithName:#"Pigeon" location:#"Everywhere"];
}
Definitely sightingList is allocated for spaces and then it's assigned to the masterBirdSightingList property. The property has a copy attribute, though. it means the instance variable _masterBirdSightingList would be allocated for another space to preserve stuffs from sightingList. Why? Why not directly allocate space for the property like this :
self.masterBirdSightingList = [[NSMutableArray alloc] init];
In Objective-C, the copy attribute in a property means the setter synthesized will look like this:
-(void)setMasterBirdSightingList:(NSMutableArray*)newValue
{
if (_masterBirdSightingList == newValue) return;
// NSMutableArray* oldValue = _masterBirdSightingList;
_masterBirdSightingList = [newValue copy];
// [oldValue release]; // <-- not applicable in ARC.
}
and that dot syntax will always be translated to
[self setMasterBirdSightingList:sightingList];
regardless of the attribute of the property.
The "allocated for another space to preserve stuffs from sightingList" stuff is done via the -copy method. The way you pass the argument to the setter's newValue parameter is irrelevant.
Edit: As #David mentioned in the comment, the -copy method of a mutable type returns an immutable object. You have to override the setter to call -mutableCopy instead. See What's the best way to use Obj-C 2.0 Properties with mutable objects, such as NSMutableArray?.

How does adding a variable as a property affect it?

What difference does it make in memory management to define a variable as a property? For instance:
#interface foo {
NSString *theStr;
}
#end
#implementation foo
- (void)bar {
NSLog(theStr);
}
#end
Versus:
#interface foo {
NSString *theStr;
}
#property(retain) NSString *theStr;
#end
#implementation foo
#synthesize theStr;
- (void)bar {
NSLog(theStr);
}
#end
It seems like the first is autoreleased or something similar, while the second is retained throughout the life of the class. Is that the case, or what is the difference?
If you define a variable just in the interface without defining it as a property (as in your first example) means that you'll have to take care of everything related to memory management yourself. Assigning something to that variable will not retain it automatically, not will setting the variable to something else release the previous value.
Defining it as a property creates getter and setter methods under the hood. Most importantly, if you use it with the "retain" keyword, your setter method will retain the new value (and release the old one if there was one).
Note that the setter method will only be invoked if you use the dot notation, e.g., self.myStr = #"new string", or the method call, e.g., [self setMyStr:#"new string"]. If you just call myStr = #"new string" the setter method will not be called and you need to release the old value yourself and retain the new one.
I don't think the first case shows an autoreleased object, it would all depend on how you managed the creation and the destruction of that particular object. If for instance when you create that object you call:
//This string will indeed be autoreleased
theStr=[NSString stringWithString:#"Jibber jabber"];
//Or even
theStr=#"Jibber jabber";
But you have to take charge of the memory management if you create it in the following way:
//Manage my memory
theStr=[[NSString alloc] init];
//You have to release this property on the dealloc method
-(void)dealloc{
[theStr release];
[super dealloc];
}
On your second example, you create a setter and a getter method for the property theStr and by adding the nonatomic attribute, you make your property not thread safety, meaning that a thread can begin to modify your property while another one is already editing it. And by setting the retain attribute to your property, the setter method will be synthesized the following way:
- (void) setTheStr:(NSString *) newString {
[newString retain];
[theStr release];
theStr = newSupervisor;
}
You can consult more about this in one of my favorite books, Learning Objective-C 2.0 in chapter 12.

Objective-C memory management and nil?

In my book a *joystick that was assigned #property (nonatomic, retain), and it wasn't released only set to nil in the -dealloc method. In the -init method, the same joystick was set to nil. What does this mean?
If you have a property like:
#property (nonatomic, retain)
the setter method generated by synthesize will take care of releasing the object currently pointed to by the ivar before assigning the new one to it. So,
self.property = xxx;
is equivalent (if you like) to:
if (property != xxx) {
[xxx retain];
[property release];
property = xxx;
}
Now, it is considered good practice to set an ivar to nil after releasing it:
[property release];
property = nil;
This is a common release idiom in ObjC.
As you see, if you assign nil to a property (i.e., xxx = nil in the example above) what you get is just this: the ivar will be released and its value set to nil. Assigning nil to a property is therefore just a shorthand for this "release idiom".
Properties are essentially automaticaly generated accessor method to you ivars, you can even override properties, so if you property is call joystick then the automatically generate method is equallent to
- (void)setJoystick:(MyType *)aValue
{
if( aValue != joystick )
{
[joystick release];
joystick = [aValue retain];
}
}
more than this actually happens if you do not have nonatomic, and there maybe stuff to deal with thread access.
Sp you can see that if you set self.joystick you are calling setJoystick: with nil and so release the current value and setting the ivar to nil

Methods from #synthesize?

When you synthesize a property (see below)
#interface CelestialBody : NSObject {
NSString *name;
}
...
#interface Planet : NSObject {
NSString *name;
int mass;
CelestialBody *moon;
}
#property(nonatomic, retain) NSString *name;
#property(assign) int *mass;
#property(nonatomic, retain) CelestialBody *moon;
...
#implementation Planet
#synthesize name;
#synthesize mass;
#synthesize moon;
...
You get setters and getters for each of the iVars (i.e.)
[newPlanet setName:#"Jupiter"];
[newPlanet setMass:57];
NSString *closestName = [newPlanet name];
int largestMass = [newPlanet mass];
CelestialBody *newMoon = [[CelestialBody alloc] initWithName:#"Callisto"];
[self setMoon:newMoon];
[newMoon release];
but you also get the ability to release the object using ...
// Releases the object (frees memory) and sets the object pointer to nil.
[self setMoon: nil];
There will of course be deallocs for each Class.
// Moon
-(void)dealloc {
[name release];
[super dealloc];
}
// Planet
-(void)dealloc {
[name release];
[moon release];
[super dealloc];
}
Am I getting this right?
gary
Unless your planet object is declared as a property within some other class, using the retain/copy attributes, you can't release it this way.
When you declare a property using retain/copy, the resulting setter will release the old value and assign the new value, retaining or copying it in the process. If you pass nil, you will release the old value and assign nil, retaining or copying it, and retaining/copying nil is nil, so effectively you end up releasing the old value and assigning nil to the ivar.
This is an acceptable way to release instance variables.
In order to be able to release your newPlanet instance this way, you'd have to have declared it in a class as a property with either retain or copy.
As a further example, since your planet object declares its properties in this way, you could release those using this method.
Or in the Planet class's dealloc method, you could do:
self.name = nil;
This would release name and assign nil to it.
"you also get the ability to release the object"
Yes, as long as you didn't declare it with the assign attribute.
As you probably know, one of the reasons (although perhaps not the primary one) for using declared properties is that you can do:
self.moon = aMoon;
rather than;
[self setMoon:aMoon];
They are equivalent. That means that your deallocation can look like this:
self.moon = nil; // Releases and sets to nil
But remember to never just do:
moon = nil; // Sets to nil, doesn't release
It's very good practice to not only release the object, but to set the variable to nil, as you do, because otherwise some other code could mistakenly try to use the pointer that is left in the variable.
Your example shows the synthesis of one class's ivars (those of Planet) but the use of another (whatever "self" is). Is the "newPlanet" property of "self" in your last example also synthesized as (retain)? If so, then: Yes, setting newPlanet to nil will release whatever self's old "newPlanet" was.
I think you are not getting it right.
After your question update, yes, you can do that, and also:
self.moon = [[CelestialBody alloc] initWithName:#"Callisto"];
and release it later, probably in your dealloc method:
self.moon = nil;
Apple Objective-c 2.0 Properties and Memory Management docs are pretty good. Check Mac Dev Center library.

Is there a difference between an "instance variable" and a "property" in Objective-c?

Is there a difference between an "instance variable" and a "property" in Objective-c?
I'm not very sure about this. I think that an "property" is an instance variable that has accessor methods, but I might think wrong.
A property is a more abstract concept. An instance variable is literally just a storage slot, like a slot in a struct. Normally other objects are never supposed to access them directly. A property, on the other hand, is an attribute of your object that can be accessed (it sounds vague and it's supposed to). Usually a property will return or set an instance variable, but it could use data from several or none at all. For example:
#interface Person : NSObject {
NSString *name;
}
#property(copy) NSString *name;
#property(copy) NSString *firstName;
#property(copy) NSString *lastName;
#end
#implementation Person
#synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:#" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:#" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
#end
(Note: The above code is buggy in that it assumes the name already exists and has at least two components (e.g. "Bill Gates" rather than just "Gates"). I felt that fixing those assumptions would make the actual point of the code less clear, so I'm just pointing it out here so nobody innocently repeats those mistakes.)
A property is a friendly way of implementing a getter/setter for some value, with additional useful features and syntax. A property can be backed by an instance variable, but you can also define the getter/setter to do something a bit more dynamic, e.g. you might define a lowerCase property on a string which dynamically creates the result rather than returning the value of some member variable.
Here's an example:
// === In your .h ===
#interface MyObject {
NSString *propertyName;
}
// ...
#property (nonatomic, retain) NSString *propertyName;
// === In your .m #implementation ===
#synthesize propertyName /* = otherVarName */;
The #property line defines a property called propertyName of type NSString *. This can be get/set using the following syntax:
myObject.propertyName = #"Hello World!";
NSLog("Value: %#", myObject.propertyName);
When you assign to or read from myObject.propertyName you are really calling setter/getter methods on the object.
The #synthesize line tells the compiler to generate these getter/setters for you, using the member variable with the same name of the property to store the value (or otherVarName if you use the syntax in comments).
Along with #synthesize you can still override one of the getter/setters by defining your own. The naming convention for these methods is setPropertyName: for the setter and propertyName (or getPropertyName, not standard) for the getter. The other will still be generated for you.
In your #property line you can define a number of attributes in parens for the property that can automate things like thread-safety and memory management. By default a property is atomic meaning the compiler will wrap #synthesized get/set calls with appropriate locks to prevent concurrency issues. You can specify the nonatomic attribute to disable this (for example on the iPhone you want to default most properties to nonatomic).
There are 3 attribute values that control memory management for any #synthesized setters. The first is retain which will automatically send release to old values of the property, and retain to the new values. This is very useful.
The second is copy which will make a copy of any values passed in rather than retaining them. It is good practice to use copy for NSString because a caller could pass in an NSMutableString and change it out from under you. copy will make a new copy of the input which only you have access to.
The third is assign which does a straight pointer assign without calling retain/release on the old or new object.
Lastly you can also use the readonly attribute to disable the setter for the property.
I use properties for the interface part - where the object interfaces with other objects
and instance variables are stuff that you need inside your class - nobody but you is supposed to see and manipulate those.
By default, a readwrite property will be backed by an instance variable, which will again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for the life of the object. The memory used for instance variables is allocated when the object is first created (through alloc), and freed when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName.
Previously people use properties publicly and ivars for private usage, but since several years ago, you can also define properties in #implementation to use them privately. But I'd still use ivars when possible, since there are less letters to type, and it runs faster according to this article. It makes sense since properties are mean to be "heavy": they are supposed to be accessed from either generated getters/setters or the ones manually written.
However, in recent codes from Apple, ivars are not used anymore. I guess because it's more like objc rather than C/C++, plus it's easier to use properties with assign, nullable, etc.
Objective-C Property vs Instance variable (iVar)
[Swift variable, property...]
Instance variable
#interface SomeClass: NSObject
NSString *someVariable;
#end
Property
#interface SomeClass: NSObject
#property (nonatomic, strong) NSString *someVariable;
#end
Property uses Instance variable inside. property = variable + bounded getter/setter. It is a method call with variable syntax and access
#property generates getter and setter methods(accessor methods) which uses backing ivar(aka backing field) which you can use via underscore _<var_name> (_someVariable).
Since it calls a method - method dispatch mechanism is used that is why KVO[About] can be applied
When you override accessor methods backing iVar is not generated that is why you can declare a new property explicitly or use #synthesize[About] to generate a new one or link with existing
#import "SomeClass.h"
#interface SomeClass()
#property (nonatomic, strong) NSString *someVariable;
#end
#implementation SomeClass
- (void) foo {
//property getter method
NSString *a1 = self.someVariable; //NSString *a1 = [self someVariable];
//property setter method
self.someVariable = #"set someVariable"; //[self setSomeVariable:#"set someVariable"];
//iVar read
NSString *a2 = _someVariable;
//iVar write
_someVariable = #"set iVar";
}
//if you overriding someVariable getter and setter the iVar(_someVariable) is not generated, that is why you can:
//1. create some variable explicitly
NSString *_someVariable;
//or
//2. use #synthesize
#synthesize someVariable = _someVariable;
//overriding
- (NSString*) someVariable {
return _someVariable;
}
- (void)setSomeVariable: (NSString*) updatedSomeVariable {
_someVariable = updatedSomeVariable;
}
#end
[property attributes]