How to release ViewController after pushviewcontroller - iphone

I have 2 view, named viewcontroller1,viewcontroller2. every viewcontroller has load about 3 pictures(load it in XIB) , when i try to use [self.navigationcontroller pushviewcontroller], to push view1 to view2, the memory cannt release.(i want to konw it cannt release viewcontrller1 or cannt release uiimageview)any error for my code ??
viewcontroller1 code just like this:
viewcontroller1.h
#interface ViewController : UIViewController
#property(strong,nonatomic)IBOutlet UIImageView *mainImageView;
#property(strong,nonatomic)IBOutlet UIImageView *topwallImageView;
#property(strong,nonatomic)IBOutlet UIImageView *buttonImageView;
viewcontroller1.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
self.mainImageView = nil;
self.topwallImageView = nil;
self.buttonImageView = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(void)dealloc
{
[mainImageView release];
[topwallImageView release];
[buttonImageView release];
[super dealloc];
}
-(IBAction)main2ViewController:(id)sender
{
Main2ViewController *main2ViewController =[[Main2ViewController alloc]initWithNibName:#"Main2ViewController" bundle:nil];
[self.navigationController pushViewController:main2ViewController animated:NO];
[main2ViewController release];
}

You have to study more detailed about Object Communication and Memory management in iOS.
Also please try to use ARC. Automatic reference counting (ARC) was introduced in the iOS 5 sdk to free Objective-C programmers from having to handle memory management by making memory management the job of the compiler.
You can convert your project to ARC enabled using this link
You can't release viewcontroller1 and its IBOutlet properties while viewcontroller2 is visible or after pushed viewcontroller2. Because you pushed viewcontroller2 from viewcontroller1.viewcontroller1 is the container/parent of viewcontroller2. viewcontroller2 will not exist with out viewcontroller1
About the IBOutlet imageview images, you can set it to nil .Eg: yourImageview.image = nil; However it will not release the IBOoutlet Imageview memory.
IBOutlet imageview will get released when a release method called to viewcontroller1 because you released it properly in viewcontroller1 dealloc method :)
About your Main2ViewController method:You handled memory properly in your code
When you call the pushViewController , it will retain the controller which is pushed by default. note that your are not the owner. It will release automatically when the controller is popped out.However you have to release the allocated Main2ViewController. So your code is fine :)

Related

CustomViewController throughout Application

I want to display a custom bar that appears on every screen of my application with buttons that work. I add the CustomViewController to my classes in the init method, and everything works correctly, except when I analyze my application I get a potential memory leak.
When I release [customViewController release], the buttons on the CustomViewController will no longer work. What is the proper way to go about implementing this solution with no memory leaks.
#import "CustomViewController.h"
#implementation CustomViewController
- (IBAction)doSomething:(id)sender
{
// Perform an action
}
#end
A ViewController which I create the CustomViewController:
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
CustomViewController *customViewController = [[CustomViewController alloc] initWithNibName:#"CustomViewController" bundle:nil];
UIView *bar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
[bar addSubview:customViewController.view];
[self.view addSubview:bar];
[bar release];
}
}
You seem to be going about implementing this the wrong way. What you actually need to do is create CustomViewController and add your toolbar to that view. Every other view controller in your app should then be made a subclass of CustomViewController.
If a custom navigation bar is the only thing you're using this superclass for, I would recommend just styling the bar directly on the UINavigationController your app is using.
The proper solution was to create a container view, and place my custom task bar inside of that view.
You said your bar has buttons? Does it release those buttons when it itself is released? Check it's viewDidLoad function.

Navigation controller stack issue after memory warning

I use UINavigationController in my program,when I situated on forth or fifth controller in navigation stack,program recieve memory warning and I can't go backwards. I press back button, navigation bar animation is taking place,but controller isn't being popped,I still see old view. Can anyone help me handle this problem?
My subviews has property:
#property (nonatomic,retain) UITableView *searchTableView;
#property (nonatomic,retain) UISegmentedControl *categorySegmentedControl;
#property (nonatomic,retain) UISearchBar *searchTableBar;
#property (nonatomic,retain) UIView *footerView;
#property (nonatomic,retain) UINavigationItem *navigationItem;
My viewDidUnload method
- (void)viewDidUnload
{
[super viewDidUnload];
self.searchTableView = nil;
self.categorySegmentedControl = nil;
self.searchTableBar = nil;
self.navigationItem = nil;
self.footerView = nil;
}
My dealloc
-(void)dealloc
{
[super dealloc];
[searchTableView release];
[categorySegmentedControl release];
[searchTableBar release];
[navigationItem release];
[footerView release];
[currentValues release];
}
And I had noticed strange regularity - this bug appears only when I move from view without tab bar to view with tab bar.
It sounds like you may be doing some setup in your controller's viewDidLoad and/or releasing stuff in viewDidUnload that should be done in initWithNibName:bundle and dealloc instead.
viewDidLoad and viewDidUnload are not called when your controller is created and destroyed, they are called when the view inside your controller is created and destroyed, and this can happen at any time, especially if you receive a memory warning when the view controller is in the background (e.g. not the top view in a navigation controller).
Make sure that you write your controllers in such a way that if the viewDidUnload gets called, or if the viewDidLoad gets called multiple times, you won't lose data or break anything.
Sorry if this answer is a bit vague, but if you post the code for your view controllers, I can probably give you more specific advice.

Question about presentModalViewController

I created a project using the View-Based Application template.
In my mainViewController:
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
UIImagePickerController *pickerController=[[UIImagePickerController alloc] init];
pickerController.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.delegate=self;
[self presentModalViewController:pickerController animated:YES];
[pickerController release];
}
I implemented the delegate already.
But when I was running this project, I didn't get the imagePicker View. Instead of the imagePicker View, the view of mainViewController was shown on screen.
Did I make some mistakes?
Thanks!!!
You have put code in a wrong place viewDidUnload is called when a view unloads from memory. put your code into viewDidAppear:(BOOL)animated method.

memory release problem

I have created a view and assigned the view to viewcontroller
UIView *newView=[[UIView alloc] initWithFrame:CGRectMake(0,0,320,460)];
in viewDidLoad method I have assigned the view to the viewcontroller
-(void)viewDidLoad{
self.view=newView;
//[view release]; In this case also the application crashing
}
-(void)dealloc{
[newView release];//IN this case also the application crashing.
[super dealloc];
}
The crash log is this.
how to release the newView? or else the viewcontroller itself will take care of releasing the newView.
In most circumstances you will do the following:
- (void) loadView {
// Don't call super here if you assign the view property
UIView *newView = [[UIView alloc] initWithFrame: [UIScreen mainScreen].applicationFrame];
self.view = newView;
[newView release];
// the view is now owned and retained by the UIViewController
}
Apple recommends you allocate the view, assign and release it in -loadView and don't worry about it in -dealloc. This is important in cases when your view may be purged under low memory conditions.

iPhone dev - viewDidLoad and viewDidUnload in programmatically created view?

I read somewhere that in a programmatically created view in a UIViewController, not using Interface Builder, -viewDidLoad and -viewDidUnload should not be used. Is this right? Why? Where would I release subviews that I have retaining properties of? Or should I just not use properties for them?
EDIT: Read my comments on Rob Napier's answer.
Create your subviews in -viewDidLoad. If you need ivars for them then only assign their values. The reference is hold by adding the views as subviews to you main view.
Then when your view is unloaded you should set your ivars to nil, because the object have been released since your view was removed and released.
So in your header
#interface MyViewController : UIViewController {
IBOutlet UIView *someSubview; // assigned
}
#property (nonatomic, assign) IBOutlet UIView someSubview;
#end
And in your implementation
#implementation MyViewController
//... some important stuff
- (void)viewDidLoad;
{
[super viewDidLoad];
someSubview = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:someSubview]; // retains someSubview
[someSubview release]; // we don't hold it
}
- (void)viewDidUnload;
{
[super viewDidUnload];
someSubview = nil; // set the pointer to nil because someSubview has been released
}
//... more important stuff
#end
If you wish you can also not release someSubview in -viewDidLoad, but then you have to release it in -viewDidUnload AND -dealloc since (if I remember right) -viewDidUnload isn't called before -dealloc. But this isn't necessary if you don't retain someSubview.
the strange thing here is that an UIViewController not loaded from a NIB file is not notified about its view unloading (and so its viewDidUnload method is not called) unless you offer a base implementation of the loadView method, such as:
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
[self.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
}
- (void)viewDidLoad {
[super viewDidLoad];
// create views...
}
- (void)viewDidUnload {
// destroy views...
[super viewDidUnload];
}
this only happens to base UIViewController, an UITableViewController for example don't need to be fixed with this workaroud.
So Robs is right.