The statement is:
//Pass the copy onto the child controller
self.childController.theFoodFacilityCopy = [self.theFoodFacility copy];
My property is set to:
#property (nonatomic, retain) FoodFacility *theFoodFacilityCopy;
The reason I think I have a leak is because copy retains the value and then my dot syntax property also retains the value. Doubly retained.
What is the correct way of writing the above statement?
yes, you do have a leak there.
SomeClass *someObj = [self.theFoodFacility copy];
self.childController.theFoodFacilityCopy = someObj;
[someObj release];
This mirrors the recommended approach for initializing an object too:
SomeClass *someObj = [[SomeClass alloc] init];
self.someProperty = someObj;
[someObj release];
In both cases the first line returns an objects with a retain count of 1, and you treat it identically after that.
As mentioned by others, that is indeed a leak. If you expect to be using copies in this way, it’s likely your property should be declared copy instead and the synthesized accessor will do the work for you.
You are right. The cleanest way is something like
id temp = [self.theFoodFacitlity copy];
self.childController.theFoodFacilityCopy = temp;
[temp release]
You want to read the apple site on memory management a lot until these rules become second nature.
What is the advantage of doing this vs just setting the property to copy?
#property (nonatomic, copy) FoodFacility *theFoodFacilityCopy;
Related
I have an NSMutableArray which is storing a list of other arrays. And when i run the code.
NSLog(#"%#",[[appDelegate teamRoster]objectAtIndex:[indexPath.row]class])
It returns and tells me that i am looking at an Array,
however when i try to do the following
[selectedRowerView tempArray] = [[appDelegate teamRoster]objectAtIndex:[indexPath.row]];
The program errors out. Anyone have any ideas why this might be happening?
You have to understand that [selectedRowerView tempArray] is actually a command / message that is being sent. In C++ equivalent, you are calling selectedRowerView->tempArray() = .... Which doesn't make logical sense because you cannot make an assignment to a function.
What you're trying to do is set the tempArray. If you have the proper setters/getters set-up, you can just run: selectedRowerView.tempArray = ...;
Just make sure that tempArray has a #property and is #synthesize'd.
How about this?
selectedRowerView.tempArray = [[appDelegate teamRoster]objectAtIndex:[indexPath.row]];
…assuming that tempArray is a synthesized property à la
#property (nonatomic, readwrite, retain) NSArray *tempArray;
#synthesize tempArray;
Clarification:
selectedRowerView.tempArray = …;
gets internally processed to
[selectedRowerView setTempArray:…];
which is a setter method.
While
selectedRowerView.tempArray;
gets internally processed to
[selectedRowerView tempArray];
which is a getter method.
Subtle but important difference.
The meaning of foo.bar depends on the very context (enclosing expression) it is used in.
I have a class that adopts the MKAnnotation protocol. Along with the two "title and "subtitle" methods to implement, I wanted to add two NSStrings, one to represent each line in a typical US address. For example:
addressLine1 = 123 street
addressline2 = northridge, ca 91326
My subtitle method currently looks like:
- (NSString *)subtitle {
NSMutableString * ret = [NSMutableString stringWithCapacity:kDefaultStringCapacity];
if (streetAddress) {
[ret appendString:streetAddress];
addressLine1 = [[NSString alloc] initWithFormat:streetAddress];
}
... more code
When would I release addressLine1? Because it is a property that I declared with (nonatomic, retain), I already released it in my dealloc method. Or am I to use a class method or autorelease the string? Thanks.
If you autorelease address1, you will lose ownership on the object and without any other owners, it will get deallocated. You would need to autorelease it if you were doing,
self.address1 = [[NSString alloc] initWithString:streetAddress];
which is wrong as you would've taken ownership twice and relinquished it only once in the dealloc method. Right way would've been,
self.address1 = [[[NSString alloc] initWithString:streetAddress] autorelease];
The direct assignment above works only if it were to be assigned a value once. If it is to be assigned again, you would lose the reference to the earlier reference and your application will leak. So it would be good process to use the property accessors here which would ensure that the older values are deallocated.
Another thing with strings is that you would copy them as you wouldn't want them to mutate after assignment so the property should be declared as #property (nonatomic, copy) rather than what it is now.
If your property is (nonatomic, retain), then you're going to leak the addressLine1 resource if you don't explicitly release it. I'd release it as soon as you're done with it. The property should then be released in your dealloc method as you are currently doing.
Somewhat unrelated to the question, but still related, is that anytime you have an object that implements the NSCopying protocol, such as NSString in this case, you should use copy instead of retain. Here's a SO question that provides some great information.
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
I am newbie to iPhone programming. I am not using Interface Builder in my programming. I have some doubt about memory management, #property topics in iPhone.
Consider the following code
#interface LoadFlag : UIViewController {
UIImage *flag;
UIImageView *preview;
}
#property (nonatomic, retain) UIImageView *preview;
#property (nonatomic, retain) UIImage *flag;
...
#implementation LoadFlag
#synthesize preview;
#synthesize flag;
- (void)viewDidLoad
{
flag = [UIImage imageNamed:#"myImage.png"]];
NSLog(#"Preview: %d\n",[preview retainCount]); //Count: 0 but shouldn't it be 1 as I am retaining it in #property in interface file
preview=[[UIImageView alloc]init];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
preview.frame=CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
preview.image = flag;
[self.view addSubview:preview];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 2
[preview release];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
}
...
When & Why(what is the need) do I have to set #property with retain (in above case for UIImage & UIImageView) ? I saw this statement in many sample programs but didn't understood the need of it.
When I declare #property (nonatomic, retain) UIImageView *preview; statement the retain Count is 0. Why doesn't it increase by 1 inspite of retaining it in #property.
Also when I declare [self.view addSubview:preview]; then retain Count increments by 1 again. In this case does the "Autorelease pool" releases for us later or we have to take care of releasing it. I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it.
Now, after the [preview release]; statement my count is 1. Now I don't need UIImageView anymore in my program so when and where should I release it so that the count becomes 0 and the memory gets deallocated. Again, I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it. What will happen if I release it in -(void) dealloc method
In the statement -> flag = [UIImage imageNamed:#"myImage.png"]]; I haven't allocated any memory to flag but how can I still use it in my program. In this case if I do not allocate memory then who allocates & deallocates memory to it or is the "flag" just a reference pointing to -> [UIImage imageNamed:#"myImage.png"]];. If it is a reference only then do i need to release it.
You say...
I am newbie to iPhone programming. I
am not using Interface Builder in my
programming.
Wait. What? Why not? Not using IB as someone new to the environment is generally an indication that you are doing your app the hard way. Not using IB for app development is reserved for rare, generally fairly advanced, situations.
Question 1
This means that the synthesized property accessor messages will include an automatic retain when the message is called (but ONLY when the message is called, see next).
Question 2
This is because you are not using the property accessor message, you are just assigning to the member variable. If you use:
self.preview = [[[UIImageView alloc] init] autorelease];
The resulting retain count will be one (+1 for the init, -1 for the autorelease, +1 for the retain on the message).
N.B.
You will get the same retain count (one) if you do this:
preview = [[UIImageView alloc] init];
(+1 for the init, not using the property accessor message so no extra retain). Up to you which way you go with.
Question 3
The addSubview will increment the retain count again because the preview will be stored in a collection which will retain it's objects.
So yes, Basically if you are handing an object off to another object to manage (as is the case with addSubview) you can set it to autorelease and it will be released by the other object. However, since you are storing the UIImageVIew in a retained property, you will need to release it yourself (see next).
Question 4
Because you are keeping the preview object as retained property, you will need to release it in your dealloc message. So in my Question 2 example, you allocate the object, autorelease it, but assign it to retained property, so the retain count after all that will be one, you are adding it to a collection which will also retain it. When the view is cleaned up the collection will decrement the retain count, but you will need to call release as well, because you stored it in a retained property. So in your dealloc:
[preview release];
Question 5
imageNamed is a helper message that does the allocation, initialization and autorelease. So basically it is equivalent to saying.
NSData * dataForImage = get data from the myImage.png here ...
self.flag = [[[UIImage alloc] initWithData:dataForImage] autorelease];
You are storing it in a retained property (because I use self.flag in the above example), so you will need to release it in the dealloc message.
When you write
flag = [UIImage imageNamed:#"myImage.png"]];
you are assigning to the instance variable directly, bypassing the property accessor. Instead you need to use the dot-notation:
self.flag = [UIImage imageNamed:#"myImage.png"]];
That explains your retain count problem.
I found it useful to declare the instance variables with a different name, like _flag for a property flag. Associate the two by writing
#property .... flag = _flag;
That way you will not accidentally use the variable directly. You can, of course, still do so if the need arises.
You use retain to claim ownership of an object. This essentially means that when something is assigned to the property, you ensure that it's there for as long as the owning object needs it.
#property ... is a statement of your the interface of your class. It doesn't mean there is a value for the property in question, only that "Instances of LoadClass have a flag property which is retained by it". Not until you actually assign values to the properties of an instance will things be retained.
This is because UIView claims ownership of its subviews.
Your object might not need it, but UIView still needs it.
It's autoreleased by UIImage.
You should read the full guide on Memory Management by Apple. I try to think of memory management as owning objects or not... it helps.
Question 2: The #property statement in your #interface is really just a directive to the compiler to automatically generate accessor methods for an instance variable that have the characteristics you specify. #property doesn't cause any actions to happen when you run your code. The compiler will look at the #property line and generate invisible accessor code for you.
#property (nonatomic, retain) UIImageView *preview;
would cause the compiler to generate accessor methods that look something like this:
- (void) setPreview:(UIImageView *)newValue {
[self willChangeValueForKey:#"preview"];
if (preview != newValue) {
[preview release];
preview = [newValue retain];
}
[self didChangeValueForKey:#"preview"];
}
- (UIImageView *) preview {
return preview;
}
#property is a timesaver for you; it directs the compiler to generate accessor code for your variables that are efficient but invisible. If you didn't use #property, you'd have to write accessor methods similar to the above in your custom class.
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.