iphone basic release question - iphone

When i add a new subview, i cant immediately release the controller after displaying. How should i release this viewController?
I was thinking about using a property for the viewController, and use delegation to notify for removing the view and releasing it?
Is this the best way to do it? or should i do something with autorelease?
Ton.

I'm going to have a shot at answering this rather vague question. I think what you are doing is creating a new subview and then releasing it. What you need to do is add it to your main view. Something like:
[myView addSubview.newSubview];
Once you have done this myView owns the subview and you can release it without hassles.

Related

Timing for add Notification observer in UIViewController subclass

I'm fairly new to Cocoa Touch. Right now I'm trying to subclass UIViewController to provide my custom view. Since I intend to save the content of a UITextField (passcodeField) using NSUserDefaults, I want to be notified whenever the UITextField changes its value.
I've read somewhere that in order to do that I should add the view controller to be an observer of the UITextFieldTextDidChangeNotification notification. However I'm just not sure when to do that. I've considered several options.
In the -loadView method. However, since I'm loading my view using a XIB, I think i shouldn't mess with this method and should instead leave it as-is. (Am I correct on this point, BTW? )
In the -viewWillAppear method. But this method may be called multiple times because the view may be moved out and into the screen without being destroyed and recreated. (Am I correct? ) This will not do any harm to the program but sure doesn't seem like the correct way.
In the initializer of the UIViewController. If I want to add the notification there I must reference the UITextField. By doing this I essentially cause the view to created before it is really needed. Also I think I read somewhere that if the system runs low on memory the offscreen views may be destroyed. Thus I may lose the notification observing if such thing happens, right?
So I'm totally confused right now. Could you guys give me some advice of where to put it? Thanks so much!
Put it in the - (void)viewDidLoad method of your ViewController remember to call [super viewDidLoad]; at the start of your implementation.

UIViewController not releasing subviews when dealloc (using ARC)

I have what seems like a weird (non?) issue with UIViewController. It appears that the controller is not releasing its subviews when it is dealloc'd. I placed NSLog messages in all of the subview's dealloc method as well as the view controller. The view controller dealloc gets called but the subview's do not. However, if I then push another instance of that view controller on to the navigation stack, it appears that all of the subviews of the previous instance are then released (I get a bunch of NSLog messages in the console letting me know). I've check and I have no separate reference to the custom view controller in the presenting view controller (the one that's doing the pushing).
One small (maybe) detail: The custom view controller does receive a block it stores and then executes before popping. However, I did send nil to it and I get the same behavior. Plus, the presenting view controller does dealloc when popped of the stack, so no retain cycle.
Also, I did try explicitly releasing each view in the dealloc method of the custom view controller. Same behavior.
Is it possible the navigation controller would be holding on to it? It doesn't seem to do this to any of my other view controllers.
My problem is that this does represent a memory leak (of all those subviews); though the leak doesn't stack, it's still a leak.
Ok, this is embarrassing. I did find the problem in another class (called ViewDef) I was inadvertently using as a collection class. It was a quick and dirty way of keeping track of my subviews when I was first figuring out some animations (months ago). ViewDef stored frame/font/color/etc info retrieved from a database, so it was convenient to also store the views when figuring out animations (between orientations). These ViewDefs were being store by my model and passed around, so of course the views were also being retained (and replaced later by another view controller). Anyway, I forgot to insert a warning in my code to fix this later.
Moral of the story: If you plan on doing something stupid, at least document your stupidity so you don't have to broadcast it over the internet later.
you could try setting the subviews to nil in the viewDidUnload method maybe that will help
One thing to try is to make sure all your subviews delegates are set to nil.

cocoa - quickly release all IBOUtlets

I have a view with many retained IBOutlets, loaded from a XIB.
I have read that they have to be released when the controller's dealloc method is called.
May I use a cycle to do this(also to avoid releasing each outlet separately)?
something like
for(UIView *v in self.view.subviews){
[v release];
v=nil;
}
?
also, after that, should I release the view as well?
That would only make sense if you've actually retained every single subview, and even then it seems like asking for trouble -- if you ever wanted to change your .xib, you'd have to remember to update you code as well. And there may also be non-view objects in a nib that can be connected to outlets, like view controllers.
There are only so many views you can fit on an iPhone- or iPad-sized screen, so it's hard to imagine that you have more than a few dozen outlets. I think the prudent thing to do here is to simply release each one separately. This is what and iOS developer would expect to see, and it won't be any slower than using a loop. It'll be more code, yes, but the code will be easy to understand.
self.view is automatically released on UIViewController deallocation, and subviews also, if not retained by your code.
You should re-read the chapter on memory management in Apple Documentation... ;)
I wrote like a releaseVars function, which takes address of variables, release them and set to nil. This save some lines of code, but still you have to manually take care of them.

iPhone: “Unrecognized Selector Sent to Instance” Error

I’m trying to implement a partial overlay modal in my app with the code from “Semi-Modal (Transparent) Dialogs on the iPhone” at ramin.firoozye.com. The overlay functionality works and it slides the modal into view, but calling any IBAction from the modal's controller causes an “Unrecognized Selector Sent to Instance” crash.
I recreated the basic functionality with that code isolated, and it triggers the same error. To see what I’m talking about, you can download the test project here.
I’m sure I’m just missing something simple here. Any help would be greatly appreciated.
When showing your ModalViewController in TestViewController displayModal:, you release your modalController (line 20). Don't do this - you need the ViewController to stay alive. If you release it, only the view keeps alive (as it is retained when added as a subview).
Also, in ModalViewController hideModalEnded you release modalView, which you didn't retain, so I'd remove that one as well.
So now you need to release just the instance of ModalViewController after the view got removed. You can do this by [self release]; in hideModalEnded, but this seems to be an unusual pattern and I don't feel good doing it.
Some suggestions:
Keep the show and hide methods in the
same class.
Keep an ivar around with the
controller.
Another possiblity: Remove the
ModalViewController altogether and
put everything in TestViewController - But this very much depends on how much action there will be going on in the real thing.

IPHONE: Test to see if a view is on the superview

I am about to do a
[vistaX removeFromSuperview];
How do I test to see if vistaX is present on the super view before removing it? Removing a view that isn't there would lead to a crash on the application...
thanks for any help.
You can guard it with:
if(vistaX.superview)
[vistaX removeFromSuperview];
Although, I wasn't aware that removeFromSuperview would fail if there wasn't a superview. Are you sure that this is the issue and it isn't maybe related to the fact that removeFromSuperview releases the view?
EDIT:
Based on your comment below, it sounds like vistaX's retain count is going to 0 the first time around and it's being freed. If you don't want this to happen, add a property to your class that retains vistaX (i.e. "#property (retain)") so you can be sure that it'll always be around.
EDIT EDIT:
Do you have a handle on the superView or one of its ancestors? If so, I would recommend setting a unique tag on the vistaX view. This can be done programmatically or through IB. Then, use the viewWithTag selector on one of the ancestors to search for the vistaX view by its unique tag.
You Can Check it By applying one condition like
if(vistaX.superview!=nil)
[vistaX removeFromSuperview];
then if superview exists, it will remove from super view, otherwise not.