Can I skip creating a separate pointer when setting my viewController? - iphone

Why do I need to create a pointer just to allocate memory and then release it immediately?
In other words, can't I just do this:
self.viewController = [[HelloWorldViewController alloc] initWithNibName:#"HelloWorldViewController" bundle:[NSBundle mainBundle]];
instead of this:
HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:#"HelloWorldViewController" bundle:[NSBundle mainBundle]];
self.viewController = newViewController;
[newViewController release];
[EDIT]
To provide wider context on my question: (within #implementation of #interface HelloWorldAppDelegate : NSObject <UIApplicationDelegate>)
#synthesize window=_window;
#synthesize viewController=_viewController;
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:#"HelloWorldViewController" bundle:[NSBundle mainBundle]];
self.viewController = newViewController;
[newViewController release];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
...
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
So, within the didFinish... method, can I use the short version I supplied way above, or would it leak?
[SECOND EDIT]
Seems I just can't give enough info. I'm always hesitant to post a huge pile of code.
I've got this in HelloWorldAppDelegate.h:
#property (nonatomic, retain) IBOutlet HelloWorldViewController *viewController;
So, correct me if I'm wrong. Given the declaration of viewController in the header file, if I use the shortcut method (in the first code snippet above), the program will leak. The object counter is incremented once by the alloc, and then a second time by the retain, then decremented once by the release, producing a net of +1 on the pointer reference counter.

You do have to release the object that you allocated, or you will end up with a memory leak. The assignment to self.viewController (presumably) retains the newly-alloc'd HelloWorldViewController, so you have two "claims" on the object -- one from your call to alloc and one from the retain, but you're not actually going to use it any more under the name newViewController, so you relinquish that particular claim by calling release.
The "long" form, using the temp variable, is in fact the correct way to do this. Sending release to the result of the property access: [self.viewController release]; right after it's set is quite likely to work, but is incorrect (and will generate a compiler warning for recent LLVM versions).
It's also possible to do this:
self.viewController = [[[HelloWorldViewController alloc] initWithNibName:#"HelloWorldViewController"
bundle:[NSBundle mainBundle]]
autorelease];
which says "I've created this thing to use it briefly, but I won't need it outside this immediate call stack, so go ahead and release it for me later."
If viewController isn't a retaining property, then all this is moot, and you should not be sending release to the new view controller, because it will then be deallocated before you can use it.
UPDATE: Your expanded question doesn't change anything*. If you don't send release before newViewController goes out of scope, you will end up with a leak.** The way this works is, any object (A, B, C) that needs to use object X, and therefore cares about keeping it around, sends retain to X. When you alloc an object, it's assumed that you need to use it. When any of A, B, or C no longer need X, it sends release to X, thereby saying "X can be deallocated and it won't affect me". You need to balance the number of claims you make (by using retain, alloc, copy/mutableCopy, or new) on an object with the number of relinquishments you make (by sending release or autorelease) or you will have either a leak or an accidental deallocation on your hands.
I'm going to give you a link to the docs now, but don't be annoyed, it's just one page that you need to read and internalize: The Fundamental Rule of Cocoa Memory Management.
*Actually, you left out the only part that could've changed the answer, namely your
#property () HelloWorldViewController * viewController;
declaration. If it says "retain" inside those parentheses, then when this property is set, your app delegate is sending retain to the passed object. If it says "assign", or the parentheses aren't there, then, like I said, you should not send release to that object.
**Note for any pedants looking on: you could of course send release twice to the viewController at some point, but that's worse than a leak.

Yes you can do this. Except you have to release self.viewController so that the retain count is 1 by the end of the snippet.
Let's count. Upon allocation, the release count is 1. Assiging it to self.viewController (assuming it's a property with retain behavior) increases it to two. Releasing it at the end of the second snippet makes it 1 again. The idea is that you'll release it completely in the dealloc of the current class, whatever that is.
The only wrinkle is that releasing an object variable assumes that you're done with it, and here you have to go, releasing self.viewController but using it later. Kinda smelly.

Related

Objective-C (iPhone) ivars and memory management

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.

iPhone - Retain Count - Retain count goes up for no apparent reason

Quick question, hopefully I am just missing something simple. Ok I have one class that holds a pointer to another; MainMenuClass and NormalGameClass. Inside of the MainMenuClass I do the following.
m_NormalGame = [[NormalGameMode alloc] initWithNibName:#"NormalGameMode" bundle:[NSBundle mainBundle]];
m_NormalGame.delegate = self;
[self presentModalViewController:m_NormalGame animated:YES];
Now, I first noticed a problem whenever the NormalGameClass' dealloc function was not being called so I did some retainCount calls and for some reason once it makes its way back to the release function in MainMenu, its retain count is 6. Further digging has me very confused. The first line after viewDidLoad in NormalGameClass its [self retainCount] is 4. Anybody have any idea what could be going on here? I only call alloc on NormalGameClass once ever, and yet it is being retained up to 6? Strangely enough never past that. Thanks for any insight.
UPDATE: Was fiddling around with things and found this to be awkward.In the MainMenuClass, here is how I get rid of the NormalGame.
[self dismissModalViewControllerAnimated:NO];
m_NormalGame.delegate = nil;
[m_NormalGame release];
Now, with this setup, the dealloc for NormalGame is never called. However, if I call [m_NormalGame release] immediately after the one posted above, it calls the dealloc for NormalGame ...twice. =/ Paint me confused.
presentModalViewController retains the passed view controller, so you need to release the view controller passed if you do not autorelease it. In this case you would need to release m_NormalGame.
m_NormalGame = [[NormalGameMode alloc] initWithNibName:#"NormalGameMode" bundle:[NSBundle mainBundle]];
m_NormalGame.delegate = self;
[self presentModalViewController:m_NormalGame animated:YES];
**[m_NormalGame release];**
I would imagine that the -dismissModalViewControllerAnimated: call is not releasing the view controller until the dismissal is complete. You do need to balance your initial -alloc/-init of the controller with a -release, but you should not expect the -dealloc method to be called immediately. It may in fact be called during the next iteration of the run loop, if the object was autoreleased.
Are you saying that without two calls to release your dealloc is not called, or is it simply not called immediately?
Also, try not to inspect retain counts as that will only lead to confusion and headaches. Just follow the memory management rules properly.

Where I should call [object release]?

I've subclassed some UITextField and added some custom properties.
In a UITableViewController, in the ViewDiDLoad I init them, and in the cellForRowAtIndexPath I add them to the cell with [cell.contentView addSubview:customTextField];
Each cell has a different customTextField as all of them are very different.
Where I should call the [customTextField release] ?
After I add them to the cell view ?
If for example I call [self.tableView reloadData] my customTextField are going to be added again to the cell, so maybe I should change my approach in doing this ?
thanks for the orientation ...
regards,
r.
You release an object when you no longer have any interest in it. This happens for many reasons; it might be because you've finished with the object, or have passed the control over the object lifetime to another object. It might be because you're about to replace the object with a fresh instance, it might be because you (the owner object) are about to die.
The last one seems to be relevant in your case. You create these object in viewDidLoad and repeatedly need them (i.e. to add them to cells) until your object is no longer functioning. In this case, just as you create them in viewDidLoad, you can release them in viewDidUnload.
Edit: I should really mention autorelease, but this isn't relevant in this instance. Memory management is best handled with a notion of 'owner' - the person who creates something (or retains it) should be responsible for deleting it (or releaseing in ObjC parlance). autorelease handle some cases where you need to give an object to an alternate owner, having previously owned it yourself (typically via a method return). If you are the creator, you can't just release it before returning it to the new owner, as it will be deleted before the new owner has a chance to stake an interest in it. However, you can't just not release it; it will leak. As such, the system provides a big list of objects that it will release on your behalf at some point in the future. You pass your release responsibility to this list, then return the object to the new owner. This list (the autorelease pool) ensures your release will occur at some point, but gives the new owner a chance to claim the object as theirs before it's released.
In your case, you have a clear interest in owning the objects for the lifetime of your view controller - you need to, at any time, be able to add them to view cells in response to a table data reload. You're only done with them when your view controller dies, so the viewDidUnload (or possibly dealloc) is the only sensible place to release them.
I always release my controls directly after I added them to a view using addSubView. When I work with tables, I also initialize them in the cellForRowAtIndexPath method.
Therefor the object stays alive the shortest time.
Adam Wright explains the theory of this very well, but let me give you some practice. You're thinking about this problem far too hard, and that almost always leads to bugs. There is a simple solution that solves this problem almost every time: Retain all ivars using accessors; don't retain non-ivars.
.h
#interface ... {
UITextField *_customTextField;
}
.m
#property (nonatomic, readwrite, retain) UITextField *customTextField;
...
#synthesize customTextField=_customTextField;
-(void)viewDiDLoad {
self.customTextField = [[[UITextField alloc] init....] autorelease];
}
...
- (void)dealloc {
// I do not recommend accessors in dealloc; but everywhere else I do
[_customTextField release]; _customTextField = nil;
}
Never access your ivars directly, except in dealloc (even that is controversial and some people recommend self.customTextField = nil; in dealloc; there are arguments either way). But never assign your ivars directly. If you will follow this rule, you will find that most of your memory problems go away.
The safest way to handle object ownership is to autorelease the view directly after initialization:
FooTextField* textField = [[[FooTextField alloc] init] autorelease];
[myCell.contentView addSubview:textField];
Adding the text field to a superview (the UITableViewCell's contentView) retains it. This way you don't have to care about releasing the view afterwards.
There seems to be a resentment against autorelease in the iPhone developer community. In my opinion, this resentment is unfounded. Autoreleasing an object adds very little overhead to the program if the objects lives longer than the current pass through the run loop.
Every object in Obj-C has a reference counter (retainCount), and when this counter goes to 0 the object is deallocated. When you allocate and initialize an object, the reference count is set to 1 - but you can retain it as many times you want to.
UITextField *textField = [[UITextField alloc] init]; // Reference counter = 1
[textField retain]; // Reference counter = 2
[textField retain]; // Reference counter = 3
The opposite of retain is release, which subtracts from the reference counter;
...
[textField release]; // Reference counter = 2
[textField release]; // Reference counter = 1
You can always get the reference counter of your objects;
printf("Retain count: %i", [textField retainCount]);
The method addSubview of UIView does retain your passed in sub view - and when it's done with it it releases it. If you need your UITextField later, in another scope (when the UIView is done with it and has released it) - you should not release it after you've added it to the super view. Most of the time you actually don't need to hold on to a reference, so you should release it after you've added it to the super view. If you dont - you can release it in the dealloc method of your scope.
Take a look at UITableView -dequeueReusableCellWithIdentifier: and -initWithStyle:reuseIdentifier:.
In -tableView:cellForRowAtIndexPath:, use -dequeueReusableCellWithIdentifier: and check if the result is nil. If it is, instantiate a new cell with -initWithStyle:reuseIdentifier:.
Send -autorelease to your customTextField upon creation and adding to the respective cell.
You should not add subview in cellForRowAtIndexPath! This will slow down the view as you add a subview each time the cell is displayed. Try using custom UITableViewCell class for that purpose.
Here is a perfect solution of UITableView customization
http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
works jut perfectly

Difference between creating a local variable and assigning to ivar and directly assigning to ivar?

I have always wondered why all apple code samples use code like this:
UINavigationController *aNavigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
self.navigationController = aNavigationController;
[self.view addSubview:[navigationController view]];
[aNavigationController release];
They always create a local variable and assign it to the ivar why don't they simply do this:
self.navigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];;
[self.view addSubview:[navigationController view]];
[navigationController release];
Is there any other reason, besides it is easier to understand?. Is this a best practice?.
-Oscar
Your replacement code is incorrect, and thus illustrates the problem that Apple is trying to prevent. Here is your code:
self.navigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
[self.view addSubview:[navigationController view]];
[navigationController release];
You left out the "self." in your references. Perhaps you meant to access the ivar directly, but in that case you have created very confusing code by mixing accessors and direct ivar access (and violated the cardinal rule by using direct ivar access outside an accessor). If not, then you meant to write this:
self.navigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
[self.view addSubview:[self.navigationController view]];
[self.navigationController release];
That last line is very wrong. Never send -release to the result of a method call. So no, the way you're doing it isn't correct.
That said, Apple and I disagree on how to do this. Here's how I do it:
self.navigationController = [[[UINavigationController alloc]
initWithRootViewController:rootViewController] autorelease;
[self.view addSubview:[self.navigationController view]];
I like -autorelease because I find it prevents errors. The further apart the alloc and release get, the more likely a developer will inject a memory leak (by adding a "return" for instance). autorelease avoids this by keeping the retain and release together, making the intent to use this as a temporary variable more clear, and generally makes code review much easier.
Apple tends to disagree with me in their example code because they're emphasizing performance by using release versus autorelease. I find this to be the wrong optimization, since this object won't be deallocated during this run loop in either case (so no memory is saved), and I believe the very small performance penalty of autorelease is more than made up for by the reduction in memory leaks due to incorrect use of release.
The autorelease vs. release debate is filled with shades of gray (I certainly use release directly in loops), and different developers have different approaches, but your replacement code isn't the right way to do it in either case.
The differences in the first lines is that Apple's version separates object creation and assignment to an ivar whereas yours puts the the two together. Conceptually, Apple's version is slightly easier to understand. It is not a best practice to my knowledge.
Both versions miss a check for a nil value:
(Assuming self.navigationController is a property that retains it's value)
self.navigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
if (self.navigationController != nil) {
[self.view addSubview: navigationController.view;
[self.navigationController release];
}
You could argue this is style, but in my opinion it leads to less buggy code.
It may be the same thing as the top example, but there's a chance it won't be.
Remember that
self.navigationController = aNavigationController;
is the same as
[self setNavigationController:aNavigationController];
and you don't know what's going on inside that setNavigationController method. It could be initializing a different object and setting that as the iVar, which you then release, causing a crash.
Since it's clear that the code is using a UINavigationController instance variable. Then there wouldn't be no reason to do:
self.navigationController = aNavigationController
If you're not retaining it.
But, if you do it like this:
self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
Afterwards, if you release it like this:
[navigationController release];
It will appear to be that we are releasing the instance variable that's supposed to be retained for the lifetime of the current class that initialize the navigation controller. So, it's prone to mistake, that will make beginners think that it should only be released in the dealloc method.
Both approach will have retain count of 0 in the end. If at the dealloc implementation:
[navigationController release]; // 1 for the ivar
[super dealloc]; // 0 for the retained subviews

Objective C iPhone when to set object references to nil

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!!!