my question is : i think that there is an error in this code ( it is not my code and i have not a Mac to compile ). this is the code :
....
CDAUIView *theView = [[CDAUIView alloc] initWithFrame:rectFrame];
theView.myController = self;
self.view = theView;
[theView autorelease];
when theView is released, wha about its property ( myController) ??
thanks for your answers
It all depends on the details behind the properties in question (specifically, whether the properties are declared as retain, copy or assign) — but that code looks fine, given reasonable assumptions. Under normal circumstances, setting a property will retain the object, and releasing the object might cause its properties to be released (that will happen if the object is deallocated). In this case, releasing the view shouldn't cause its myController to be released, because it's still being owned by self here. But even if it were, the release would just be balancing the retain.
An object doesn't retain its instance variables whenever it's retained, and it doesn't release them just because it's released. It retains them when it takes ownership it and releases them when it is ready to relinquish ownership.
If CDAUIView is written correctly, when it gets deallocated it will release any objects that it has retained.
Related
I have a MBProgressHUD that I allocate as follows:
self.progressHUD_ = [[[MBProgressHUD alloc] initWithView:self.view] autorelease];
if I call removeFromSuperview then would I have to call progressHUD release again? Also if I declare a property with something like this:
NSString * title_;
#property (nonatomic, retain) NSString * title_;
then it is guaranteed that in my dealloc I should have a release on title right?
If progressHUD_ is a retain property, then you will have to release it in dealloc. However, the nice thing about a retain property is that you only have to set it to nil to reclaim the memory; making sure to use "self." before.
e.g.
self.<property_name> = nil;
// or in your case
self.progressHUD_ = nil;
// the following will not release it because it's not accessing the property:
progressHUD_ = nil
I do not recommend using [progressHUD_ release] because it can cause problems. e.g. if elsewhere you had released progressHUD_ and not set it to nil, you may accidentally release a pointer which is no longer allocated (dangling pointer).
I also recommend calling self.progressHUD_ = nil; in viewDidUnload which is called during low memory conditions and the view is not showing. It doesn't kill your class instance, but just unloads the view. And of course this assumes that you call self.progressHUD_ = [[[MBProgressHUD alloc] initWithView:self.view] autorelease]; in viewDidLoad rather than in init...
No, you don't have to release it again. Views retain their subviews and release them again automatically when you call removeFromSuperview. As long as the view has been autoreleased when you attach it to the view, it will be released when it is removed from the view.
I didn't quite understand your second question, but yes, you have to release any properties of type "retain" or "copy" in your dealloc statement. You have to write those release statements manually, they aren't added automatically (unless you are using ARC of course, which I strongly recommend).
How is your progressHUD_ property defined? (btw, the ivar should have a trailing underscore, but not the property name).
In case it is defined as (retain, whatever), you will have to release it again:
When you create it, its retainCount is +1.
When you assign it to your property, its retainCount will be increased by one.
When you add it as a subview to the parent view, its retainCount will be increased by one.
At some point, autorelease will eventually decrease it by 1, but the view and the property still hold on to it.
So you'll have to either set your property to nil or call release on the ivar in your dealloc method.
Also, you probably want to use copy instead of retain when defining an NSString property. And yes: you'll have to release it either way.
In a class derived from UIViewController there is a message implementation that is accessing derived property view like this:
- (void) doSomethingOnView
{
MyView *v = (MyView *) [self view];
[v doOnView:YES];
[v release];
}
According to quick documentation on property view of UIView it is a nonatomic read-write property in retain mode. My books here (e.g. "Beginning iPhone 4 Development" by Mark, Nutting, LaMarche) are reading that on reading properties in retain mode a release on obtained reference is required.
But my analyzer complains the [v release] with "Incorrect decrement of the reference count of an object that is not owned at this point by the caller". Where is my fault?
In your first line, MyView *v is just a pointer that is being set to point to a property already owned by your UIViewControllwer. You UIViewController has it through inheritence. It is declared elsewhere, not by you, therefore it is not alloced by you.
When you set a pointer to point to an object which you never explicitly alloced or retained, you don't need to release it, because you never increased its reference count. Read more here if you are curious.
So the point is, don't call [v release];.
Consider the following code:
self.view = anotherView;
Then if viewis a property which is declared as retain, anotherView will be implicitly retained.
This works when you are assigning a variable.
In your code:
You are not using properties (i.e. the dot notation)
You are not assigning any variable
You try to release something you did not allocate yourself with alloc for instance
Try reading the Declared Properties and Memory management guide sections of Apple's Objective-C documentation again if that is not clear.
You didn't alloc the view, so you do not need to release it.
Where in the book are you reading that a release is needed in this case?
I think you misinterpreted what the book says. if you provide a quote we can explain it to you further.
In this case, you don't need to release cause there were no alloc or retain sent to v.
There are a few concepts about iPhone memory management that have got me confused, so I was hoping that someone could clarify these.
(a) Say that I am calling a function which returns an image, and I want to store that returned image in a variable so that I can assign it to various other variables without having to re-call the image generation function each time. At the moment I am doing the following:
UIImage *storedImage = [someFunction returnImage];
and because the storedImage is not alloc'ed I am not releasing the variable.
However, should I be explicitly alloc'ing and releasing the UIImage instead?
UIImage *storedImage = [[UIImage alloc] init];
storedImage = [someFunction returnImage];
...do stuff...
[storedImage release];
What is the implication of doing the direct assignment without alloc rather than alloc'ing the variable and then assigning?
(b) In the init method for various classes I am setting up the instance variables. At the moment I am doing the following:
self.arrayVariable = [[NSMutableArray alloc] init];
However, I have seen others do the assignment this way:
theArrayVariable = [[NSMutableArray alloc] init];
self.arrayVariable = theArrayVariable;
[theArrayVariable release];
or
theArrayVariable = [[NSMutableArray alloc] init];
arrayVariable = theArrayVariable;
[theArrayVariable release];
...which is the same as above, but without the self.
What is the difference between the three methods and which is better to use?
Regarding returning objects from methods, you should always return an autoreleased object from any method which does not begin with the name alloc, new, or contains copy. This is defined in Apple's object ownership policy, which states that you own any object that you create ("create" is defined as an object which you sent retain to, or used any of the aforementioned messages to retrieve an object), and that you are responsible for relinquishing ownership of that object by sending it the release or autorelease message.
The first method using self uses the property setter to set the instance variable to the argument (in this case whatever is on the RHS of the assignment).
This will do whatever you specified in your #property declaration (for example if you specified retain, the setter will retain the new value and release the old value).
The second method sets up a pointer to an NSMutableArray and passes it off to your property setter via self, which will most likely retain it, thereby bringing the reference count up to 2, since the object was previously alloc-ed, so you need to release it after this line to bring it back down to 1.
The third method will not work, because you are releasing an object with a reference count of 1 at the point of invoking release. How so you ask? Well, the first line sets up a pointer to an alloc-ed object, then directly assigns it to your instance variable, which will just point the ivar to the same object that theArrayVariable is pointing to. Then, that same object that theArrayVariable is pointing to gets sent the release method, which will effectively bring down the reference count of your ivar as well as the receiver, to 0. At this point both your instance variable and theArrayVariable will get deallocated.
a) The general rule for objective-c is that if you alloc it you must release it. In the first example, the method is returning a pointer to an object that already exists, and therefore you are not responsible for releasing it. In the second example, the first like is pointless since you aren't using allocated memory for stored image. This may cause a memory leak.
b) The first two are just stylistic differences, with no difference in outcome. In those, you will be left with arrayVariable pointing to the object returned by [[NSMutableArray alloc] init]; (assuming you have retain in the #property declaration) and you should release it in the -dealloc method. As stated above, the third will not work because you are merely passing off the pointer.
Here is a useful article for understanding obj-c memory management: http://memo.tv/memory_management_with_objective_c_cocoa_iphone
a) The code you gave does not do what you want. When you say
UIImage *storedImage = [someFunction returnImage];
someFunction returns an image object to you, but it does not guarantee that the image object will live forever. If you do not want the image to be freed without your permission in a future time, you should own it by calling retain like this:
UIImage *storedImage = [[someFunction returnImage] retain];
So now, this image object is owned by both someFunction and you. When you finish your work with this object you release it by calling release. When both someFunction and you call release for this object, it will be released (Of course if it is not owned by another owner).
In the other code segment, you create an image object and own it by calling
UIImage *storedImage = [[UIImage alloc] init];
But then you lose its reference by assigning a new object to the storedImage pointer by calling someFunction. In this situation the image created by you is not freed but continues to live somewhere in the memory.
I am subclassing NSURLConnection, and used MGTwitterEngine as a base to help me get started. That may be irrelevant. However, I noticed in their code they don't use #property or #synthesize for their ivars. They have wrapped the ivars in accessor methods which look like this:
- (NSString *)identifier {
return [[_identifier retain] autorelease];
}
My question is two part. First, what effect does retain followed by autorelease have? It seems to me it would cancel itself, or worse yet leak.
Second, if I were to change the header file to have:
#property (nonatomic, retain, readonly) NSString* _identifier;
And used #synthesize indentifier = _identifier, wouldn't this do the same thing as the accessor method without having to write it?
Maybe it is just two different ways to do the same thing. But I wanted to ensure I have the correct understanding. Thanks.
Using #synthesize will actually only create a setter and a getter method. The code that is auto generated for you is guaranteed to use proper memory management, so that you do not need to worry.
MGTwitterEngines use of return [[ivar retain] autorelease] is actually the correct way to do it. Lets have two examples.
Assume a getter is defined as this:
-(Foo)foo {
return foo;
}
And then we execute this code:
bar = [[bar alloc] init]; // bar has aretain count of 1.
foo = bar.foo; // foo har a retain count of 1 (owned by bar).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // This will crash since the previous line released foo.
If we instead change the getter to this:
-(Foo)foo {
return [[foo retain] autorelease];
}
bar = [[bar alloc] init]; // bar has a retain count of 1
foo = bar.foo; // foo has a retain count of 2 (one owned by bar, 1 owned by autorelease pool).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // Will not crash since foo is still alive and owned by autorelease pool.
Hope this explains why you should always return properly autoreleased objects from all your getters. It is important that any return value can survive the deallocation of it's parent, since no class ca guarantee what a client will do with it's values once it is exposed to the wild.
Retain followed by autorelease does exactly what you might think it does. It sends the object a retain message and then sends it an autorelease message. Remember that autoreleasing an object adds that object to the autorelease pool but does not release it yet. The autorelease pool will send the object a release message at the end of the current iteration of the run loop. So, a retain followed by autorelease essentially says, "Make sure this object stays around until the end of the the current iteration of the run loop." If you need the returned value to hang around longer, you can retain it. If not, do nothing and the autorelease pool will handle it.
In this case, the string being sent retain and autorelease messages is a property. It's already retained by the parent object. So you might wonder why do this retain and autorelease thing at all? Well, there's no guarantee that the object won't release _identifier before the current iteration of the run loop ends. Consider this example:
- (NSString *)identifier { return _identifier; }
- (void)aMethod {
NSString *localId = [self identifier]; // localId refers to _identifier which is only retained by self
[self methodThatChangesIdentifierAndReleasesItsOldValue]; // self releases _identifier
NSLog(#"%#", localId); // crash, because localId (old value of _identifier) has been released
}
In this case, the returned identifier isn't retained and autoreleased. The NSLog line crashes because localId refers to a released string. However, had we used retain and autorelease in the getter, there would be no crash because localId would not be released until the end of the current iteration of the run loop.
As far as I know, your replacement with an identifier property would be just as good. It might not be identical code, but the effect should be the same.
Apple explains this well in Implementing Accessor Methods. The method quoted by you (named "Technique 1" by Apple) helps avoid bugs if the caller assigns a new value to the identifier property and then expects the retrieved value to still be available. It won't be needed most of the time but just returning the ivar value can lead to bugs that are hard to track down.
Generally one retains then autoreleases if you are returning something that you didn't own the first place. It will only leak if you own _identifier and there is a mismatch of retain/alloc/etc versus release/autorelease sent to that object.
Secondly, yeah you generally don't have to write the headers if you aren't doing something special beyond what the general boilerplate looks like. Apple has good documentation on properties, I suggest if you're still fuzzy, you look at those.
I have been developing with objective C and the Cocoa framework for quite some time now. However it is still not absolutely clear to me, when am I supposed to set object references to nil. I know it is recommended to do so right before releasing an object that has a delegate and you should also do so in the viewDidUnload method for retained subviews. But exactly when should this be done and why?. What does it accomplish exactly?. Thank you in advance.
-Oscar
Say you have a pointer myView defined in your class' interface:
#interface MyClass {
UIView *myView;
}
#end
Then in your code, at some point, you may release that variable:
[myView release];
After you do that, myView, the pointer, won't be pointing to nil, but will be pointing to a memory address of an object that may not exist anymore (since you just released it). So, if you happen to do something after this, like:
[myView addSubview:otherView];
you'll get an error.
If, on the other hand, you do this:
[myView release];
myView = nil;
...
[myView addSubview:otherView];
the call to addSubview will not have any negative impact, since messages to nil are ignored.
As a corollary, you may see suggestions of using retain properties, such as:
#property(retain) UIView *myView;
and then in the code, just do:
self.myView = nil;
By doing that, the synthesized accessor will release the old object and set the reference to nil in one line of code. This may prove useful if you want to make sure all your properties are both released and set to nil.
One thing that you must never forget, is that memory management is done by means of retain release calls, and not by means of assigning nil. If you have an object with a retain count of 1, and assign nil to it's sole variable, you'll be leaking memory:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,10,10)];
view = nil;
// You just leaked a UIView instance!!!