In one controller I add other controller's view in the following way:
objSecondController = nil;
objSecondController = [[SecondController alloc]initWithNibName:#"SecondController"
bundle:nil];
[self.view addSubview:objSecondController.view];
In view did load of objSecondController I do the following:
self.pdfView = [[PDFView alloc] init];
[self.view addSubview:self.pdfView.view];
and then I specify pdf according to its methods
In one of button clicks method for changing the pdf I do the following:
if(self.pdfView)
{
[self.pdfView.view removeFromSuperview];
[self.pdfView release];
self.pdfView = nil;
}
and then again do:
self.pdfView = [[PDFView alloc] init];
[self.view addSubview:self.pdfView.view];
and then I specify pdf according to its methods
Now self.pdfView is third party library, whenever I use self.pdfview its retain count increases automatically so when I release self.pdfView its retain count does not become 0 and so it does not dealloc though I release them.
The pdf are as large as 25MB and 39 MB so as the previous memory does not dealloc totally it crashes due to excess memory.
What should I do so self.pdfView releases memory completely, so it does not create problem while loading other large pdf?
Assuming you have properly implemented setter/getter methods, then you are retaining the pdfView one-too-many-times with this code:
self.pdfView = [[PDFView alloc] init];
[self.view addSubview:self.pdfView.view];
This is because the setter for pdfView will also call retain.
You need to use:
self.pdfView = [[[PDFView alloc] init] autorelease];
[self.view addSubview:self.pdfView.view];
Also remove this statement, as it's not necessary:
[self.pdfView release];
As this is sufficient:
self.pdfView = nil;
I would suggest allocating pdfView in the init method and releasing it in dealloc and just changing the PDF within the view in both viewDidLoad and whenever the Change PDF button is pressed. There is no need to init/addSubview/removeFromSuperview/release the PDFView object whenever its content should change.
Related
I want to allocate memory for the variable to which i have allocated already.for example
self.m_tabbarController = [[TabbarController alloc] init];
I have to change assigned view controller for above tabbar controller.so i have to release
the above and allocate the same tabbar with new controllers. how can I release and allocate
new one.If i do the following, gives crashes.
if(self.m_tabbarController != nil)
{
[self.m_tabbarController release];
}
self.m_tabbarController = [[TabbarController alloc] init];
but self variable must be deallcated in dealloc method.any help please?if i do like following also, it gives crash?
m_tabbarController = [[TabbarController alloc] init];
[self.window addSubview:m_tabbarController ];
[m_tabbarController release];
First release it. Assuming your synthesised property is retain, the implementation will handle the release for you:
self.m_tabbarController = [[[TabbarController alloc] init] autorelease];
In short, you cannot rely on some way to reinitialize an instance unless you implement some kind of reinitialization method in the class.
If that's a UIViewController, just create a new UIViewController because you would need to know a lot about an implementation, all subclasses, and all members/ivars to implement reinitialization correctly. Sometimes you can accomplish this via its public properties, sometimes you won;t be able to reinitialize an instance correctly.
One problem with reinitialization is that what you alloc may not be what's returned -- and you may not otherwise know what type you are dealing with specifically in all cases. Proper, exhaustive reimplementation of a complex type adds a lot of implementation (which tends to be transitive too).
self.m_tabbarController = nil;
TabbarController *tempController = [[TabbarController alloc] init];
self.m_tabbarController = tempController;
[tempController release];
tempController = nil;
You should declare m_tabbarController with retain kind of property.
Now, modify your code as below:
TabbarController *temp = [[TabbarController alloc] init];
self.m_tabbarController = temp;
[temp release];
Also, release m_tabbarController into dealloc method.
[self.m_tabbarController release]; will release m_tabbarController not self so
if(self.m_tabbarController != nil)
{
[self.m_tabbarController release];
}
self.m_tabbarController = [[TabbarController alloc] init];
is absolutely fine
Part of my code presents a UITableViewController in the following way:
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"Settings" bundle:nil];
flipside = [[UINavigationController alloc] initWithRootViewController:controller];
controller.delegate = self;
flipside.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:flipside animated:YES];
[flipside release];
[controller release];
Using the leaks tools, no memory leaks are picked up on. However, whenever I bring up the settings menu (as shown in the code above), more memory appears to be allocated and never released - almost 100 kB every time.
Weirdly, the inclusion of the two release statements at the end seems to have no effect on the memory allocation..? Is there something I am misunderstanding about memory allocation in objective-c, or is something weird going on?
Any ideas are much appreciated - thanks!
If flipside is a retained property then the navigation controller is leaking. the problem is that you are bypassing the accessor method and releasing flipside directly. This is just messy code. A better way to do it would be to make an accessor method for flipside that will only alloc a new one if you haven't already created one. It's called lazy loading. To do this, just leave the #synthesize for flipside (but you shouldn't set it from outside the accessor method), in your header file change the property to, and add this method to the implementation:
- (UINavigationController *)flipside {
if (flipside != nil) {
return flipside;
}
FlipsideViewController *controller = [[[[FlipsideViewController alloc] initWithNibName:#"Settings" bundle:nil];
controller.delegate = self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[controller release];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
// This implies a retain if your flipside property is set to retain
self.flipside = navController;
[navController release];
}
make sure to put self.flipside = nil in the viewDidUnload method of the view controller the code you included came from (I assume it's a presentSettings action).
what your presentSetting action should now look like is this:
- (IBAction)presentSettings {
// make sure you use the accessor self.flipside instead on accessing the variable directly
[self presentModalViewController:self.flipside animated:YES];
}
my image picker is initialized like:
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsEditing = YES;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
presentation:
[self initImagePickerFromLibrary]; ----(this calls the lines I have mentioned before)
[self presentModalViewController:self.imgPicker animated:YES];
[imgPicker release];
apple instrument says:
before calling the picker memory used is 3 Mb.While the picker is in function 12Mb.While editing image is 28Mb and my app crashes.Anyone did find a solution for this?
The one thing that comes to mind is that you're doing self. which may mean that your image picker is retained twice. Once, because you're allocating it and once because you're using a setter.
What does the #property line look like for imgPicker? Does it have retain? If it does, you should either change the first line in your first quote above to:
imgPicker = [[UIImagePickerController alloc] init];
I.e. removing self..
Also in your second line, you're releasing imgPicker directly. If your #property does have retain, you should instead just do:
self.imgPicker = nil;
The reason is that the #property synthesizing retains and releases objects when you set them. If you release the imgPicker without setting it to nil, and then, later on, try to set it to a new value, the system will attempt to release the already released object, and probably crash. The above is the same as doing:
[imgPicker release];
imgPicker = nil;
I have a view which is slideshow settings, and another view which has a slideshow. Unfortunately, these views conflict because they are still in memory.
As far as I know, viewDidUnload and dealloc are only called in low-memory situations, and dealloc should not be called directly, so how do I completely remove a view. These views are within uinavigationcontrollers by the way.
If you've added a view with UINavigationController remove it with PopViewController.
Pseudocode:
UIView *newView = [[UIView alloc] init]; // retain = 1
[UINavigationController pushView: newView]; // retain = 2
[newView release]; //retain = 1
[UINavigationController popView]; //retain = 0, object will get destroyed
I am going over my code and trying to get a handle on proper memory management. This code:
imageView = [[[UIImageView alloc] initWithImage:myImage] autorelease];
Causes my application to crash. I am using multiple view controllers within a nav bar controller. The app works fine: I can select a person from the first view controller (tableview) and it puts me to a list of that persons photos, I can then select a photo from that view controller (tableview) and move to a final view with a scrollview for viewing the photo. Once I hit back on the navbar the previous view loads (list of photos in a tableview) however the app crashes right before the row is deselected using this code:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(RowSelected != nil)
{
[MainTableView deselectRowAtIndexPath:RowSelected animated:YES];
}
}
The selected row is stored when a the user clicks a row.
If I leave the code as:
imageView = [[UIImageView alloc] initWithImage:myImage];
The app runs fine. Am I doing something wrong? Do I not need to autorelease this?
Make sure you create that view in your view controller's -loadView or -viewDidLoad, not in its initializer. When the controller's view goes offscreen it usually gets released, which in turn releases its subviews; thus, you should not expect your reference to imageView to remain valid. If you for some reason need the image view to stay in memory even when the view controller's offscreen, then it's okay not to call -autorelease when you create it; just make sure to call [imageView release]; in your controller's -dealloc.
When you mark imageView for autorelease, it will be released the next time thru the run loop. If you still are referencing or using imageView somewhere then you are using a pointer to heap space that has been released. The heap space will get overwritten (sooner or later) and you will be referencing garbage and crash.
I think the correct solution is that imageView should be a property that is retained, but I'm not sure what you are doing with imageView so I'm only guesstimating here. If you add imageView to your view Controllers view it will retain it in the subviews array. Bottom line, it has to be retained by whoever is using it.
You would make imageView a retained property in the .h file:
#property (nonatomic, retain) UIImageView* imageView;
Then use the setter, which will retain it:
UIImageView* tmpIV = [[UIImageView alloc] initWithImage:myImage];
self.imageView = tmpIV; // copy the pointer, setter will retain it
[tmpIV release]; // release the original alloc
Don't forget the #synthesize to create the setter/getter.
The ImageView is in my .h. I am using this line it in my -viewDidLoad, i do not need the view once it goes offscreen:
imageView = [[[UIImageView alloc] initWithImage:myImage] autorelease];
I think that what i am doing is assigning the allocated UIImageView to my imageView and if i auto release then the retaincount will be off because my -dealloc releases? (corret me if im wrong)
if i check my -dealloc:
- (void)dealloc {
NSLog(#"%i", [photo retainCount]);
[photo release];
NSLog(#"%i", [imageView retainCount]);
[imageView release];
[super dealloc];
}
The retaincount of the imageView is 1 in NSLog, im guessing that when it goes to do [super dealloc] that it tries to take 1 more retain count off of the imageView when it is 0 already because of the [imageView release] ?
if i have the line: imageView = [[UIImageView alloc] initWithImage:myImage];
then the retain count is 2 in NSLog, 1 going into the [supper dealloc]
if i use kk6yb's method, then the app works no problems, however i think i shouldn't have to do it this way because using his way if i check my retain count in dealloc it is also 2 in the NSLog...
I am confused, i read alot about memory management yesterday to get a better grip on things, since i am releasing the imageView in the -dealloc i believe i do not need to autorelease on that line?
Is there a way to check memory leaks in xCode?
Thanks!