#property/#synthesize question - iphone

I'm going through all of my documentation regarding memory management and I'm a bit confused about something.
When you use #property, it creates getters/setters for the object:
.h:
#property (retain, nonatomic) NSString *myString
.m:
#synthesize myString
I understand that, but where I get confused is the use of self. I see different syntax in different blogs and books. I've seen:
myString = [NSString alloc] initWithString:#"Hi there"];
or
self.myString = [NSString alloc] initWithString:#"Hi there"];
Then in dealloc I see:
self.myString = nil;
or
[myString release];
or
self.myString = nil;
[myString release];
On this site, someone stated that using self adds another increment to the retain count? Is that true, I haven't seen that anywhere.
Do the automatic getters/setters that are provided autorelease?
Which is the correct way of doing all of this?
Thanks!

If you are not using the dot syntax you are not using any setter or getter.
The next thing is, it depends on how the property has been declared.
Let's assume something like this:
#property (nonatomic, retain) Article *article;
...
#synthesize article;
Assigning something to article with
self.article = [[Article alloc] init];
will overretain the instance given back by alloc/init and cause a leak. This is because the setter of article will retain it and will release any previous instance for you.
So you could rewrite it as:
self.article = [[[Article alloc] init] autorelease];
Doing this
article = [[Article alloc] init];
is also ok, but could involve a leak as article may hold a reference to an instance already. So freeing the value beforehand would be needed:
[article release];
article = [[Article alloc] init];
Freeing memory could be done with
[article release];
or with
self.article = nil;
The first one does access the field directly, no setters/getters involved. The second one sets nil to the field by using a setter. Which will release the current instance, if there is one before setting it to nil.
This construct
self.myString = nil;
[myString release];
is just too much, it actually sends release to nil, which is harmless but also needless.
You just have to mentally map hat using the dot syntax is using accessor methods:
self.article = newArticle
// is
[self setArticle:newArticle];
and
myArticle = self.article;
// is
myArticle = [self article];
Some suggestions on reading, all official documents by Apple:
The Objective-C Programming Language
Dot Syntax
Declared Properties
Memory Management Programming Guide
Object Ownership and Disposal
Using Accessor Methods

When you create a retain setter, you're creating something like this:
- (void)setString:(NSString *)someString {
if (someString != string) {
[string release];
[someString retain];
string = someString;
}
}
If you don't use the setter, the new value is not getting that retain—you don't "own" that string, and because it's all references, if the original string is released, you might be facing a null reference, which will lead to an EXC_BAD_ACCESS. Using the setter ensures that your class now has a copy of that value—so yes, it does increment the retain count of the new value. (Note that using the getter is a convention of OOP—that outsiders should not be able to directly touch the ivar. Also in your getter you can modify the value, maybe returning an NSArray when your ivar is an NSMutableArray, for example).
You shouldn't autorelease in a setter—Apple has used it in their sample code, but a thing to keep in mind is that setters are called a lot—millions of times, potentially. All of those objects are going into the same autorelease pool, so unless you create your own and/or regularly flush it, you'll have a ton of elements in your pool, all unneeded but still taking up RAM. Much better to simply release.
As for dealloc, trace back through that setter. If you send a release directly, it's obvious—you release that object. But if you write self.string = nil;, what you're doing is this:
The nil value is not the same, so you enter the if block
You release the old value—what you want to do
You retain nil: messages to nil do nothing, and you don't crash
You set nil, which doesn't take up any memory, to the string, which is now effectively empty
As a matter of convention, I use release in my dealloc method, because release seems more final, and dealloc is the final method call your object will receive. I use self.string = nil; in viewDidUnload and the memory warning methods.
Hope this helps!

In addition to Nick's answer - synthesized getters/setters don't provide autorelease (btw, what's the big idea of doing this? Well, you can use getter as a factory, but it's not a common way in Objective C).
Then in dealloc I see:
self.myString = nil;
or
[myString release];
or
self.myString = nil; [myString
release];
In dealloc it doesn't really matter which form of release you're using. But the good way is to nil your fields when releasing them :) I prefer to use self.myString = nil; in dealloc

Related

Does NSStringFromCGPoint return an autoreleased object?

Question #1
Will NSStringFromCGPoint() return an autorelease object or does the object needs to be released?
Question #2
When you have a property : #property (nonatomic, retain) NSString *someString;
And you set it like so: self.someString = [[[NSString alloc] initWithString:#"Something"] autorelease];
Is this:
[someString release];
someString = nil;
equal to
self.someString = nil;
I haven't checked that one specifically, but by convention those sorts of functions return autoreleased objects. You might be able to test this yourself by setting up a minimal, non-ARC project and calling -retainCount on what you get out of the function, but I'm not sure. (And in general, retainCount isn't something you want to use.)
Yes. The synthesized setter looks something like:
- (void)setSomeString:(NSString *)string
{
if (string != someString) {
[someString release];
}
someString = [string retain];
}
So, whether you call it explicitly or using the dot notation, the old value gets released (and the underlying ivar gets set to nil or whatever you pass in).
Also, I'm not sure if you were just doing it for a random example, but you don't have to wrap a string literal in memory management code to pass it to the property accessor. (That is, self.someString = #"Something" is fine.)
Does the call include the term "new", "alloc", "copy", or "create"? If not, you're getting back an object that you do not own (you may assume it is either autoreleased or that the reference is owned elsewhere).

assignment of property and allocation leads to retain count of 2

I had a look at instruments and I saw that the alloc increased the retain count by 1. So far everything clear. But the assignment of the class to my property also increased the retain count to 2.
self.myProperty = [[MyClass alloc] init]
Vs.
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable
To decrease the retain count to zero I released myCreatedVariable right after my calls. The myProperty instance variable is released in the dealloc method. Am I right that a property only is released in the dealloc method?
Now to my question:
Is the allocation and the assignment to a property always creating a retain count of 2? So don't use
self.myProperty = [[MyClass alloc] init]
because the retain count is never getting zero? Or is this only the case if I'm allocating a class?
Cheers
Your property is most probably declared as retaining or copying:
#property (retain) MyClass myProperty;
or
#property (copy) MyClass myProperty;
This calls your setter that does what its attributes say: retain! Copy will also retain.
Although it worked here, you shouldn't try to get useful information out of the retainCount property.
I cannot recommend the Memory Management Programming Guide highly enough, well worth a first, second and third read. :-)
Creating objects using the init function returns a retained instance by default. ( See the Memory Management Programming Guide)
If the property is defined with the 'retain' attribute, then your object is retained one more time.
So the right way to do is
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable;
[myCreatedVariable release];
By the way this is good to know also when you using Arrays.
Once an object created with the alloc and init functions is added into an array, it is retained by the array, so you can release your instance after you add it in the array.
In both case, retainCount is then 1, as expected.
if your property is defined with the 'copy' attribute, you can release the object as well, and even kill it, since it has been fully copied and retained once.
( I think there is something there if you use garbage collection instead of managed memory... To check.. )
Finally if your property is set with the 'assign' attribute, only the object's adress is copied, so you should not release your original object in this case.
It is however not recommanded to use the 'assign' attribute, since you may set property with objects that you did not create yourself, and which could be released anytime, letting your property pointing in the fields...
Finally, don't forget that static creators in Cocoa do not return retained objects.
( This is a convention, exceptions may exist... )
example:
NSArray* myArray = [NSArray array];
self.myProperty = myArray;
In this case, do not release myArray, it is already done in the creator function.
Assigning it to the property will retain it.( with retain or copy attribute).
Hope it will help,
Cheers
#property (nonatomic, retain) NSString *strURL;
This will keep the Retain count = 0
When you use an accessor to initialize the strURL then the retain count increases to 1
self.strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
However if you had done this without using the accessor then your reference count would have remain same that is 0
strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
Note that when you use this variable with retain count as 0, the auto release works and the variable gets released, giving "SIGABART" error or “EXC_BAD_ACCESS” when you try to access its value.
Generally when you are using init to get your variables initialized the best practice is to use alloc.
strURL = [[NSString alloc] stringWithString:#"http://192.168.1.25/shop.php"];
Hope this helps!
Sorry ? Noooo. I'm afraid programming is trying to know things we don't know everyday !
Static creators are convenience function, to ease common objects allocations.
A lot of classes in the cocoa framework have this kind of functions. Arrays, Dictionary, Paths, ...
Let's take your class as an example, and suppose you often have to create objects of this class. You may write a function in your 'myClass' implementation like:
+(MyClass*)myClass
{
MyClass *myNewInstance = [[myNewInstance alloc] init];
return [myNewInstance autorelease];
}
Then you can rewrite your original example as:
..
self.myProperty = [MyClass myClass];
..
Straight!
Or you could write a method like
-(void)myFunction
{
MyClass* myTempObject = [MyClass myClass];
if (myTempObject) {
// do something with your temporary object
}
// Simply exit, object will be released later on.
}
It is much shorter ( we should handle the case where object creation failed ) ..
Note that this is all conventions, you can basically do has you like and create retained objects, or use a different name for the creator.
But it is safer to follow the framework rule, it then becomes a reflex when you code.
See methods like [NSDictionary dictionary], [NSArray array], [NSArray arrayWithObjects:] ,...
Cheers

What's the best way to release objective-c properties?

I'm new to memory-management, and am reading different things about how to best release properties.
If I have:
in .h:
#property(retain) NSString *myStr;
and in .m:
#synthesize myStr = _iVarStr;
Should my dealloc have:
[_iVarStr release];
or
self.myStr = nil;
or something else?
Thanks!
Both self.myStr = nil and [myStr release] ultimately do the same thing.
Calling [myStr release] is obvious and just releases it.
Meanwhile, the setter method for myStr looks roughly like this:
- (void)setMyStr:(NSString *)newMyStr
{
[newMyStr retain];
[myStr release];
myStr = newMyStr;
}
So when we do self.myStr = nil, we're first retaining a nil object, which does nothing. Then we release the old variable, which is what we want. Finally, we set the pointer to nil.
What's the difference? The latter sets the pointer to nil. This is better because if we (accidentally) send a message to the released object, we crash if the pointer isn't nil (EXC_BAD_ACCESS). Now honestly, since you're in -dealloc, the object is being destroyed anyways, so it wouldn't really matter what you use.
When a property is set to retain then
self.ivar = nil;
will properly manage the memory allocation. For other property types check the at the official documentation page. It also has a bunch of sample code so you can understand what happens "under the hood" for all the options.
Your dealloc should be this:
- (void)dealloc {
[_iVarStr release];
[super dealloc];
}
Although setting the property to nil is possible, I worry about unintended side effects or KVO actions triggered by the change that may not realize the object is currently being deallocated.
I recommend you use self.ivar=nil(the code ivar=nil previously I wrote was wrong) way in dealloc method. Because, if the ivar's property change from retain to assign (or from assign to retain), you don't have to change your code.

Objective-C Setter Memory Management

Still a little confused about Objective-C memory management. I think my confusion stems from what exactly the autorelease means.
NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];
Now, what should I do with the accountDictionary in the setAccountDictionary method of my view controller? Right now I just set the instance variable "accountDictionary" to whatever is returned. Should I set it to a retained one, and then release the one that's returned? What should my setter code block look like, given that NSString's propertyList method is autoreleased?
By the way, if I release theBackendResponse, will I lose the accountDictionary? I assume not...
Calling [objectInstance autorelease] adds an object to the current NSAutoreleasePool. When that pool receives a drain message, it sends a release to all the objects in the pool. If any of those objects' retainCount reaches 0, they are deallocated at that point. The purpose of autorelease is to allow you to mark an object to be released "some time in the future". This is especially useful for things like methods that return a newly allocated object but want to release it so that the caller doesn't have to take ownership of the returned object. A method might look like this:
- (id)myMethod {
id myObj = [[SomeClass alloc] init];
...
return [myObj autorelease];
}
The caller of myMethod would then retain the return value if they wanted to take ownership of the returned value or ignore it if not. When the current NSAutoreleasePool is drained, myObj will get a release message. If no other objects own it (i.e. have sent it a retain message), it will get deallocated.
All of this is explained in the Cocoa Memory Management Programming Guide. Even if you've already read it, it's always worth an other read.
So, to answer your questions:
First, you should release theBackendResponse. You will leak memory if you do not. You don't need to know what accountDictionary does with the string: if it needs to keep a reference it will have retained theBackendResponse. You have an ownership of theBackendResponse because you alloc'd it, so you must relinquish that ownership (via release or indirectly via autorelease).
Second, you must retain or copy the argument to setAccountDictionary: if you want to keep a reference to that object or value respectively. The standard setter method looks something like this (assuming you do not need atomic semantics):
-(void)setAccountDictionary:(NSDictionary*)newDict {
if(newDict != accountDictionary) {
id tmp = accountDictionary;
accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
[tmp release];
}
}
You must also remember to release accountDictionary in the dealloc method:
- (void)dealloc {
[accountDictionary release];
[super dealloc];
}
Since you appear to be using NSViewController, I assume you're on Leopard (OS X 10.5) in which case, you should probably be using #property and the #synthesized getter/setter if possible. To do this, add a
#property (copy,readwrite) NSDictionary * accountDictionary;
declaration to the class #interface. And add a #synthesize accountDictionary; directive in the #implementation block for your controller class.
In general, one object or method should not have to care about how another is managing memory. The fact that somebody else has autoreleased something is irrelevant to you. It's simpler to think of the concept of ownership. So retain and some other methods claim ownership, and release and autorelease relinquish it. If an object needs to keep a reference to another, it should claim ownership for as long as it needs. Thus, setter methods usually either retain or copy the new value and release or autorelease the old value.
I strongly recommend reading the Cocoa memory management guidelines. They're not all that long or complicated, and it's very important to understand them.
The set accessor method should always copy / retain the incoming value before releasing the old, in the case where the old value is the only object that owns the new value:
-(void)setAccountDictionary:(NSDictionary*)newDict {
id old = accountDictionary;
accountDictionary = [newDict copy];
[old release];
}
If accountDictionary referred to newDict and the retain count for newDict was 1, the call to [accountDictionary release] before the call to [newDict copy] would cause the retain count to got to 0 and therefore release newDict.
As an example of incorrect code, where we release the old dictionary and then copy the new dictionary:
-(void)setAccountDictionary:(NSDictionary*)newDict {
[accountDictionary release];
accountDictionary = [newDict copy];
}
and have the following code:
NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];
It's contrived, but it demonstrates that in the setter, accountDictionary and newDict refer to the same instance. If the retain count is 1, the [accountDictionary release] line will decrease the retain count to 0, and thus release the instance from memory. [newDict copy] will now refer to an invalid instance.
Apple describes several concepts when implementing accessors: Memory Management Accessor Methods
If you can use Objective-C 2.0, I would go with properties and dot syntax.
Properties are new in Objective-C 2.0 and provide auto accessor generation.
In the .h File:
#property (retain) NSDictionary* accountDictionary;
In the implementation:
#synthesize accountDictionary;
Synthesize generates accessor methods for your NSDictionary. (If you want to provide your own implementation, you could also do that)

release/autorelease confusion in cocoa for iphone

I'm slowly teaching myself cocoa for the iPhone(through the Stanford Class on iTunes U) and I've just gone through the part on memory management, and I wanted to hopefully get some confirmation that the assumptions I'm making on how memory is handled and how [release] and [autorelease] work. Since memory management is a really basic and fundamental, but very essential part of the programming experience, I'd like to make sure I'm doing it right.
I understand that anything with an alloc, new, or copy needs to be released.
If I do this:
NSString *temp = [[NSString alloc] initWithString:#"Hello World"];
Then I need to add [temp release/autorelease] eventually, since I have an alloc.
However, if I do this:
NSString *temp = #"Hello World";
Then it doesn't seem to need a release statement. Does the NSString class call autorelease automatically as part of the assignment?
Also, is there any difference between the two *temp objects here after these statements? They both contain the same string, but are there memory/usage ways where they differ?
Secondly, with properties, I'm assuming that the autorelease is handled automatically. If I have this:
#interface Person : NSObject
{
//ivars
NSString *firstName;
NSString *lastName;
}
//properties
#property NSString *firstName;
#property NSString *lastName;
///next file
#implementation Person
#synthesize firstName;
#synthesize lastName;
- (void) dealloc
{
//HERE!!!!
[super dealloc];
}
I'm assuming I don't need to add [firstName release] and [lastName release] (at //HERE!!!!), since that's automatically handled by the properties. Is that correct?
I do understand that if I do this in code(assuming I've defined initWithFirstName):
Person *Me = [[Person alloc] initWithFirstName: #"Drew", lastName:"McGhie"];
that later I'm going to have to use [Me release/autorelease];
Any help confirming or correcting my understanding so far is greatly appreciated.
POST ANSWER WRITE-UP
I thought I'd write this all up after going over all the answers and testing out the suggestions and talk about what worked.
I do need to add the [firstName release], [lastName release], but I also need to add (retain) to the property descriptions. Not adding the (retain) caused warnings because it assumes (assign). Here's how I finally set up the class
#interface Person : NSObject
{
//ivars
NSString *firstName;
NSString *lastName;
}
//properties
#property (retain) NSString *firstName;
#property (retain) NSString *lastName;
///next file
#implementation Person
#synthesize firstName;
#synthesize lastName;
- (void) dealloc
{
[firstName release];
[lastName release];
[super dealloc];
}
The rule is simple: if you alloc, copy or retain, it's your responsibility to release. If you didn't, it's not. However, if you need to rely on an object staying around, you have to retain (and subsequently release).
We can treat the string literal according to the rules - you don't need to release it because you don't own it. That's simple; there's no need to worry about whether they're special cases or not, just follow the rules and you'll be fine.
I wrote up a blog post with a collection of articles about the Cocoa memory management rules; I'd recommend following up some of the references.
I've never released string constants like NSString *foo = #"x";. Logically, if you had to release the result of that, it you would have to release the parameter to initWithString, and both the parameters to initWithFirstName:lastName:, too.
You must do release or autorelease firstName and lastName. I've seen warnings about not using property syntax in destructors, which I think is the same reason you don't use virtual functions in C++ constructors and destructors.
Your assumption was wrong. You must do either this:
Person *Me = [[Person alloc] initWithFirstName: #"Drew"
lastName: #"McGhie"];
...
[Me release];
or this:
Person *Me = [Person personWithFirstName: #"Drew"
lastName: #"McGhie"];
...and make sure your Person object handles +personWithFirstName:lastName: correctly, i.e. [[[self alloc] initWithFirstName: firstName lastName: lastName] autorelease].
You should probably do the one with less code. Clarity is important, NSAutoreleasePool will probably never be your bottleneck, and if it ever is it's easily fixed.
I think people put a lot of effort into avoiding the class messages that return an autorelease'd object that just isn't merited. It's premature optimization, in that it probably isn't necessary and may not even be the correct thing to do. And it's harder to maintain, you'll very likely be chasing leaks forever.
Also, you're going to autorelease an object you had to init (i.e. alloc + initPersonWithFirstName:lastName: instead of using a class message like personWithFirstName:lastName:), I'd suggest you do it immediately. Otherwise, you're potentially chasing that same kind of leak. So if you're not going to add a personWithFirstName:lastName: method to Person, do this instead:
Person *Me = [[[Person alloc] initWithFirstName: #"Drew"
lastName: #"McGhie"] autorelease];
Summary: Cocoa does a lot to help you with memory management. Make sure you don't fight it.
Updated based on Jon's feedback in comment.
NSStrings created with the #"String here" syntax are constant strings. These are different from normal strings. Much like normal C constant strings, they are created when your program loads and exist for its entire lifetime. The NXConstantString class, to which they belong, ignores all memory management messages. You can retain and release them all you like and it won't make any difference.
For a string created with an [[NSString alloc] initWith...]-type method, normal memory management rules apply. I'd strongly recommend reading the linked docs — they're not complicated, and after reading them, you will know pretty much everything you will ever need to know about Cocoa memory management.
Last part first: You will indeed have to auto/release Me. However, you will also have to add [firstName release]; and [lastName release]; in -dealloc; or better yet; self.firstName = nil;
As for string literals; this part gets a bit hairy, but [#"String literal" release] is essentially a noop. As such, there is a difference between the two temp objects, but as you won't generally know which one you'll be dealing with, adding [temp release]; is generally the safe choice, unless you know it'll contain an autoreleased object.
About firstName/lastName.
You should always, for clarity, remember to specify the properties' attributes. The setter default attribute is assign, in this case you want to use retain.
#interface Person : NSObject
{
NSString *firstName;
}
#property (retain) NSString *firstName;
#end
With retain each and only time you use the dot notation to assign a value the compiler inserts a retain: just remember to always use it. For consistency I advice you to write your initializer this way:
- (id) initWithFirstName:(NSString*) aString
{
self.firstName = aString;
}
and the dealloc method this way:
- (void) dealloc
{
self.firstName = nil;
}
About #""-type objects. They are constant NSStrings objects. Just use them as the were (they are) NSString objects and never release them. The compiler takes care of them.
Does the NSString class call autorelease automatically as part of the assignment?
The NSString class didn't do anything because you didn't send it a message. All you did was assign to a variable. NSString doesn't find out about this, and it's none of its business.
Also, is there any difference between the two *temp objects here after these statements? They both contain the same string, but are there memory/usage ways where they differ?
They're both NSStrings, they both contain the same value, and they're both presumed immutable. That's all you should ever care about.
Secondly, with properties, I'm assuming that the autorelease is handled automatically. If I have this:
#property NSString *firstName;
#property NSString *lastName;
- (void) dealloc
{
//HERE!!!!
[super dealloc];
}
I'm assuming I don't need to add [firstName release] and [lastName release] (at //HERE!!!!), since that's automatically handled by the properties. Is that correct?
No. NSObject will not release all your property values for you; you still need to release them yourself there.
Also, don't do self.firstName = nil and self.lastName = nil in dealloc. Those translate into messages (to your accessor methods), and when you do that in dealloc, you're sending messages to a half-deallocked object. That's asking for trouble. The same applies the other way to initializing property values in init: Using your properties/accessors there would be sending messages to a half-inited object.