Objective c - Correct way to release an UIVIewController - objective-c

I'm having problems releasing UIView controller, this is my code.
When I press a button, I put a View on the screen in front of everything:
viewT = [[PersonalViewController alloc] initWithNibName:#"PersonalViewController" bundle:[NSBundle mainBundle]];
//In this moment the retainCount is 1
[[AppDelegate appDelegate].window insertSubview:viewT.view aboveSubview:[AppDelegate appDelegate].dockController.view];
[viewT release];
//Now the retain count is 3!
//... After some code, when the user press another button, I want to release the view
[viewT.view removeFromSuperview];
//After this line, the object stills there, with a retain of 2.
So something it's happening and I don't understand. I've been reading guides about memory and I've never had this doubt before, what am I doing wrong? How can I completely release viewT???

You own any object you create when
You create an object using a method whose name begins with “alloc”,
“new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or
mutableCopy).
When you no longer need it, you must relinquish ownership of an
object you own
You relinquish ownership of an object by sending it a release message
or an autorelease message. In Cocoa terminology, relinquishing
ownership of an object is therefore typically referred to as
“releasing” an object.
You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated
explicitly.
Memory Management Programming Guide
So, you need only one line of code
[viewT release];

You probably have a retain cycle. Do any of the objects in your nib have an outlet connected to File's Owner? Is that outlet declared retain? (Or strong if you're using ARC, which you're not.) Change the outlet to assign (or weak if using ARC).

Related

What does ARC do if I forcefully point an allocated object's pointer to nil?

I am allocating an object like
A *a = [[A alloc] init];
At another point I am forcefully setting
a = nil;
Does it flash a message to ARC that the object can be released now?
Quick answer - YES.
Once you set your object to nil it will get killed by Arc (most of the cases, from my experience you can lay your trust on ARC)
Dealloc methods in arc will be created for you. You must not make a dealloc call directly. However you can still create a custom dealloc method if you need to release resources other than instance variables. When creating a custom dealloc method, do not call the [super dealloc] method. This will be done for you and is enforced by the compiler.
You can read more about it here
I think the original object you were pointing at (an empty A object you created with alloc/init) will be released, but you can still use your "a" pointer, and make it point at another object.

Do we release an argument in fast enumeration

do we release an argument in fast enumeration? Therefore would this code be accurate:
for (MKCircle *circle in localOverlays) {
[mapView addOverlay: circle];
[circle release]; // Is it perfectly alright to call this?
}
I am just wondering, my first time working with fast enumeration!
The answer is in the Apple Memory Management Rules.
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”
Did you create circle? No.
You can take ownership of an object using retain
Did you retain circle? No.
So you don't own the object.
You must not relinquish ownership of an object you do not own
That seems fairly straight forward now that you have determined you don't own circle. The release in the example code in your question should not be there. In fact, most likely, it will cause a crash somewhere down the line.
Fast enumeration does not usually create new objects, it is going through the existing ones. That is why it is almost never the right thing to do: fast enumeration of regular containers (NSArray, NSSet, NSDictionary) does not retain objects before making them available to the loop, so releasing them would be an error. Even inside a dealloc method you shouldn't do it: releasing the container releases its items too, so you shouldn't be releasing them individually.
No. I don't think it's the right thing to do. It neither do a retain nor a release to the instance
for (MKCircle *circle in localOverlays) {
[mapView addOverlay: circle]; //retain here
}
addOverley: should do a retain to circle, and it's mapView's responsibility to release when mapView doesn't needs it
Simple guide, you retain it, and release it when you done using it

Large retain count with a recent created object. Objective-C

I'm getting an strange case of excessive retain counts for a view controller that I'm loading when a button is pushed.
This is the code:
-(IBAction)new
{
if (!viewSpace)
viewSpace = [[ViewSpace alloc] initWithNibName:#"ViewSpace" bundle:nil];
viewSpace.delegate = self;
viewSpace.view.frame = CGRectMake(0, 0, viewSpace.view.frame.size.width, viewSpace.view.frame.size.height);
[self presentModalViewController:viewSpace animated:YES];
NSLog(#"Count Retain: %d",[viewSpace retainCount]);
}
-(void)viewSpaceWasDissmissed:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
[viewSpace release];
NSLog(#"Count Retain: %d",[viewSpace retainCount]);
}
When the IBAction New is executed first time, the retain count is 5 when just is created. (It must be 1).
When the ViewSpace object must be unload calls viewSpaceWasDismissed function in order to remove the modal view and release the previous object.
The problem is that never the retain count reach 0 and the dealloc method of ViewSpace never is called causing memory leaks.
My question is how is possible that a recently created ViewController have 5 retains? I made sure that is never created before.
Thanks.
Cocoa is probably retaining the view controller 4 times internally for reasons of its own. This isn't a problem.
More generally, the -retainCount method is useless for reasons like this, and you should never call it. It will not help you, and it will confuse you.
To debug your leak, I suggest using the leaks Instrument, inspecting the object, and analyzing where each retain and release is coming from to determine whether any are incorrect.
Check the documentation for -retainCount. I believe it says that you should not be calling it yourself - you just need to take care of any retains that you cause, and don't worry about the 'actual' retain count.
You're doing two things wrong here:
The Current view controller retains the modally presented view controller and releaseds it when it is dismissed. So you should release viewSpace after it is presented, and you don't need the release message in the dismissModalViewController method. As an aside ViewSpace is a poor name for a view controller. I had to read to the line where you are presenting it as a view controller before I knew it was a view controller. I think ViewSpaceController is a more descriptive name.
You are using retainCount which is always a bad idea. All that matters is that in your new method you created an owned object (with the alloc) and you balanced that ownership with a release (or at least you will do when you put in the correction I suggested in point 1) That's it. You took ownership of an object and you released it. The retainCount method tells you absolutely nothing that can be of any use to you. Don't do it. Just balance ownerships with release, and that is all that matters.
I'm not 100% sure of every count but here are some:
Instantiation - 1
NIB - 1+
Strong Properties (1+)
Additionally any properties that list it as a strong property (in ARC).
I noticed that when you launch a nib and you use components of the controller in the nib design, it will increase reference counts (in a strong manner) on the controller instance.

What is the difference between dealloc and viewdidunload?

When should I release all the memory I allocated in my program?
Because I only have a viewDidLoad method where I do my business. Should I leave dealloc empty and cleanup only in viewDidUnload?
'dealloc' is used when the object is ready to be freed (i.e., when retain count of the object becomes 0). And viewDidUnload is called when the view is unloaded, but it may not be freed immediately as the reference of the UIViewController is still stored by some other objects.
my personal preference is, for ojbects created by 'init', they are freed by 'dealloc', for objects created by 'viewDidLoad', they are freed by 'viewDidUnload'.
As the documentation of -viewDidUnload says:
It is called during low-memory
conditions when the view controller
needs to release its view and any
objects associated with that view to
free up memory. Because view
controllers often store references to
views and other view-related objects,
you should use this method to
relinquish ownership in those objects
so that the memory for them can be
reclaimed. You should do this only for
objects that you can easily recreate
later, either in your viewDidLoad
method or from other parts of your
application. You should not use this
method to release user data or any
other information that cannot be
easily recreated.
Typically, a view controller stores
references to objects using an outlet,
which is a variable or property that
includes the IBOutlet keyword and is
configured using Interface Builder. A
view controller may also store
pointers to objects that it creates
programmatically, such as in the
viewDidLoad method. The preferred way
to relinquish ownership of any object
(including those in outlets) is to use
the corresponding accessor method to
set the value of the object to nil.
However, if you do not have an
accessor method for a given object,
you may have to release the object
explicitly.
There is no mention -viewDidUnload will call in -dealloc, you shouldn't rely on it.

What does 'release' means in this situation on iPhone?

I want to ask a stupid question about the iPhone application. I am the green of the iPhone app. I read the following code in the Apple website.
MyViewController *aViewController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:[NSBundle mainBundle]];
[self setMyViewController:aViewController];
[aViewController release];
And I have a question, how it means of the 'release' in the line 3?
Does it presents the memory clear? or the program take control of that object? or other meanings. Thank you very much.
When you alloc something, the object you get will have a retain count of 1 - this means that this object is currently being used by someone, so it should not be removed from memory. If you call retain on an object it will increase the retain count, meaning the object is being used by 2 things. If the retain count reaches 0, it implies that the object is no longer being used by anything and it can be removed from memory. You can decrease an object's retain count by calling release on the object.
In your example, aViewController is alloc'd and after line 1 has a retain count of +1.
It is then set as the view controller in line 2. This method is therefor taking ownership of the object, so should retain it for its own use.
Line 3, we don't want anything more to do with the view controller, so we release our hold of it. The retain count decreases by one - and it is now up to the new owner to release it when it is finished with it.
You might find it helpful to read through the memory management section of this tutrial
Whenever you call alloc, you own a reference to the object that comes back, and you must call release to indicate that you no longer intend to use that reference.
In the above case, you have allocated a new view controller and assigned it to a property of your class. Assuming the property is declared with the retain option, the property will acquire its own reference to the view controller by called retain on it. So there are now two active references to it. The property will eventually release its reference (either when it is assigned a different view controller, or when your class is finalised). But if you don't call release yourself, one reference will remain, and the view controller will never be freed.
In short, you must match every alloc with a release, otherwise things will leak.