I hope to load an ViewController and do something then unload (viewDidUnload) it from memory.
if (self.vViewController5.view.superview==nil)
{
ViewController5 *blueController =
[[ViewController5 alloc] initWithNibName:#"View5" bundle:nil];
self.vViewController5 = blueController;
[self.vViewController5 setDelegate:self];
[blueController release];
}
[self presentModalViewController:vViewController5 animated:YES];
later, call
[self dismissModalViewControllerAnimated:YES];
but I found that dismissModalViewControllerAnimated does not trigger the event viewDidUnload of Viewcontroller5.
I try function release but it caused program collapse.
I also try removeFromSuperView but it does not trigger the event ViewDidUnload neither.
Welcome any comment
Thanks
interdev
viewDidUnload is only called when your application receives a memory warning, and the view is not active. It's generally used for releasing retained views (including IBOutlets). You can use viewWillDisappear or viewDidDisappear to respond to a dismissal (dealloc will also be called eventually, but not necessarily exactly when the view is dismissed).
A dismissed UIViewController will not trigger the viewDidUnload, as you have discovered. However it will trigger viewWillDisappear method, if that suit your needs.
Related
i am using addSubView method to add views. Did any alternative methods are there for viewWillDisappear? viewWillDisappear is not firing. I want to release all allocated objects when the current view get dissapear. Currently i am using dealloc method to do this. But dealloc method is firing not quickly. Since i am getting memory warings and sometimes the my app may crash itself. The main problem is with voice files.
addSubview/removeFromSuperview (these methods relate with views not view controllers) doesnt call viewWillAppear/viewWillDisappear methods. You should write release object code in dealloc() itself.
removeFromSuperview should call dealloc().
You can try to release objects in method viewDidDisappear. Then you won't wait for firing method dealloc.
Also in method viewDidDisappear you can try to remove all subviews from superview (that will call viewWillDisappear to all subviews):
NSArray *subviews = [self.view subviews];
for (UIView *view in subviews)
[view removeFromSuperview];
release objects in viewDidUnload/viewDidDisappear and set to nil in dealloc
this might work, but you should surely look why viewWillDisappear is not called.
I have a UIViewController (call it NumberTwo) which I presented as a modal view controller from another UIViewController (call it NumberOne). NumberTwo contains a touchesBegan method which listens for touches, and it also has an accelerometer method which listens for device orientation changes in the x, y, or z direction. NumberTwo has a button called "Done" which, when tapped, dismisses itself as a modal view controller:
[self dismissModalViewControllerAnimated:NO];
But it seems as though it's still listening for touches, and it's still listening for accelerations. How can I completely free up NumberTwo when I dismiss it? I tried adding a release call as follows:
[self dismissModalViewControllerAnimated:NO];
[self release];
but that caused a EXEC_BAD_ACCESS.
Did you release the controller after you presented it? E.g. in your method in NumberOneController that presents it, do you have something like:
NumberTwoController * controller = [NumberTwoController alloc] init];
// do stuff to config controller
[self presentModalViewController: controller];
[controller release];
Unless you want to hang on to NumberTwoController for re-use, this would be the usual pattern. The presentModalViewController method ensures that the controller is retained while it's in use. It should then get tidied up when, within NumberTwoController, you call [self dismissModalViewControllerAnimated: NO].
I had a very similar issue that plagued me for days. It turned out that my view controller class wasn't being deallocated when I dismissed it because that view controller had an active NSTimer that wasn't being invalidated (stopped). I was able to kill the timer in viewDidDisappear.
Make sure you are releasing everything you use when you finish with it; The dealloc method is only called when the UIViewController and all of its properties/objects are no longer in use. Never use [self release]; you need to release it from the view controller that created it after you are finished with it.
I have A UINavigationController with a table view. As it's standard behaviour when an item in the list is selected I push a customViewController to the UINavigationController. The CustomView Appears and I see my back button in the title bar.
My question is, when I hit the back button in the title bar to navigate back to my list what function do I implement to make sure that everything that was created in the customViewController is completely destroyed and removed from memory?
I tried putting my cleanup code in the viewdidunload method of the custom controller but that doesnt even get entered when I hit the back button.
(Also I wasnt really sure how to phrase this question so suggestions are welcome)
Apple explains everything very clearly in their documenation (with pretty pictures and everything!). Basically, when you show the view you use pushViewController:animated: and when you go back you use popViewControllerAnimated:.
Use something like this to go to the new screen:
- (IBAction)goSomewhereButtonPressed:(id)sender {
SomewhereViewController *vc = [[SomewhereViewController alloc] initWithNibName:#"SomewhereView" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
When the BACK button is pressed, it will clean-up your screen. Apple recommends you use UINavigationControllerDelegate for additional setup & cleanup if needed.
Put the cleanup for the screen in its controller (SomewhereViewController).
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
NSLog(#"Somewhere's viewDidUnload called");
}
- (void)dealloc
{
[super dealloc];
NSLog(#"Somewhere's dealloc called");
}
I always put my cleanup code in dealloc:
-(void)dealloc {
// cleanup code here
[super dealloc];
}
The allocated controllers inside a UINAvigationController will be removed automatically. If you need to let just one live, create the detail controller globally in your navigation controller instead every time you need to go to the detail view, so you will use always the same controller. You can clean it when the back button is pressed through the method viewDidDisappear.
The viewDidUnload method of UIViewController seems to be a good place to do memory cleanup, i.e. release all objects that can be easily recreated in viewDidLoad or later.
But it's not guaranteed that the view controller itself will be dealloc'ed. The UINavigationController may cache the object internally.
i have an array used to populate the UITableView.
The question is where i should to allocate memory for it. I have two options in viewDidLoad or viewWillAppear, but i don't know where is more efficient from the point of view of memory management.
Thanks
Edit:
I create the view doing the following:
NextViewController *nextController = [[ReservationsViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
nextController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:nextController animated:YES];
[nextController release];
But i don't want to allocate memory every time is shown, only the first time the view is loaded in order to be right from the point of view of memory-management.
If you only want it to be allocated once then you should alloc it either in the init method or in awakeFromNib depending on how your view controller is created.
viewWillAppear will likely be called multiple times and viewDidLoad is not guaranteed to be called only once.
If the array is a property just release it in the dealloc like so:
- (void)dealloc {
[someArray release];
[super dealloc];
}
If for some reason you switch to creating a local array in the viewDidLoad or viewWillAppear method make sure you release it as soon as your done with it.
If you allocate memory in the viewDidLoad method it will be done only when the view is loaded to memory. If you do this in the viewWillAppear you will be doing this every time the view becomes visible.
I have my UIPopoverController with self as a delegate:
I receive calls when I tap outside the popover controller, but when I tap inside I want to dismiss too, so I use -dismissPopoverAnimated: but delegate is not called in this case.
Is this normal? Is this a bug or I am doing something wrong?
newDocPopoverController = [[UIPopoverController alloc] initWithContentViewController:vc];
[newDocPopoverController setPopoverContentSize:CGSizeMake(240, 44*4)];
[newDocPopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
[newDocPopoverController setDelegate:self];
UPDATE:
Oh, regardless the origin of the problem (Whether is a bug or this is the intended behavior) calling the delegate by myself solves the problem :)
When the contentViewController's view is touched I will call parent UIPopoverController's delegate a call.
if ([parentPopoverController.delegate popoverControllerShouldDismissPopover:parentPopoverController]){
[parentPopoverController dismissPopoverAnimated:YES];
[parentPopoverController.delegate popoverControllerDidDismissPopover:parentPopoverController];
}r];
That's normal, expected behavior.
Quoting the Apple docs on popoverControllerDidDismissPopover::
The popover controller does not call this method in response to programmatic calls to the dismissPopoverAnimated: method. If you dismiss the popover programmatically, you should perform any cleanup actions immediately after calling the dismissPopoverAnimated: method.
Programmatically the popoverControllerDidDismissPopover does not get called and won't dismissed, you'll have to call the delegate yourself:
[self.PopUp dismissPopoverAnimated:YES];
[self.PopUp.delegate popoverControllerDidDismissPopover:self.PopUp];
Where PopUp is the parent UIPopoverController
Hope this helps
Cheers
Al
set the delegate first;
yourPopup.delegate=self;
then some where in your code (May be in Particular Method call due some event).
use the following code;
[self.yourPopUp dismissPopoverAnimated:YES];