image picker controller takes insane memory even if released - iphone

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;

Related

want to completely dealloc object's memory

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.

allocating Memory to the variable which has been already allocated?

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

application crashed after dismiss presentModalViewController

i have a problem when going to another controller with the following buttons
-(IBAction)art:(id)sender{
TestYourInfoViewController *test = [[TestYourInfoViewController alloc]
initWithNibName:#"TestYourInfoViewController" bundle:[NSBundle mainBundle]];
test.questionType = #"art";
testYourInfoViewC = test;
[testYourInfoViewC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self.navigationController presentModalViewController:testYourInfoViewC animated:YES ];
[test release];
}
and when i go back with the following
-(IBAction)back:(id)sender{
[[self parentViewController] dismissModalViewControllerAnimated:YES];
}
it crash the application with no stacktrace.. what is the wrong with that please.
Is testYourInfoViewC defined in the header as a retained #property? If so, you should always be referring to it using self and dot notation.
- (IBAction)art:(id)sender
{
TestYourInfoViewController *test = [[TestYourInfoViewController alloc]
initWithNibName:#"TestYourInfoViewController" bundle:[NSBundle mainBundle]];
test.questionType = #"art";
self.testYourInfoViewC = test;
[self.testYourInfoViewC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self.navigationController presentModalViewController:self.testYourInfoViewC animated:YES ];
[test release];
}
When you create a retained #property and #synthesize it, a setter is being created that handles the memory management involved in retaining the new object and releasing the old, but by assigning test to testYourInfoViewC you're bypassing that synthesized setter.
Let's step through this here. You've created test using alloc/init, thus setting its retainCount to 1. Next you've assigned testYourInfoViewC to test. No change in the retain count, testYourInfoViewC is now simply pointing to the same object as test instead of retaining a copy for itself.
Now when you call release on test that retain count returns to 0 and the object is deallocated. Your instance of TestYourInfoViewController is completely gone and testYourInfoViewC is now left flapping in the wind. When attempting to dismiss it, the parentViewController is going to attempt to send some messages to that object behind the scenes, like -viewWillDisappear:, -viewDidDisappear: etc.
Edit: Here's how I handle this kind of situation in my projects. I override the getter for the property and determine whether it needs to be created or not. This way I can call the property anywhere in my code and I can be assured that if its not created it will be allocated, initialized and setup just in time.
- (TestYourInfoViewController *)testYourInfoViewC
{
if (!testYourInfoViewC)
{
testYourInfoViewC = [[TestYourInfoViewController alloc] init]; // This will work because the .xib and class name are identical.
[testYourInfoViewC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
}
return testYourInfoViewC;
}
After you've setup the getter to provide lazy instantiation, your -art: method will look like this...
- (IBAction)art:(id)sender
{
[self.navigationController presentModalViewController:self.testYourInfoViewC animated:YES];
}

Bad memory leak when creating a view - even though a 'release' is present?

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];
}

Memory management on the array initialized for UITabBarController

I am still learning the ropes of Objective C and iPhone development. My weak point is memory management - any help will be much appreciated.
In the code below, where can I release the NSMutableArray listOfViewControllers? Keep in mind the function createTabs can be called within the app multiple times and the tabs are recreated dynamically based on user input. This function is within a ViewController.
If i do [listofViewControllers release] just before exiting the function, the app crashes when I have to call createTabs again
If I use a convenience method like below:
NSMutableArray *listOfViewControllers = [NSMutableArray arrayWithCapacity:1]
instead of:
NSMutableArray *listOfViewControllers = [[NSMutableArray alloc] init]
it still crashes when createTabs is called again
-(void) createTabs
{
//TODO - memory management - where do you release this?
NSMutableArray *listOfViewControllers = [[NSMutableArray alloc] init];
if ([briefingsArray count] > 0)
{
//add briefing(s) tab(s)
for (Briefing *briefing in briefingsArray)
{
WebViewController *briefingViewController = [[WebViewController alloc] initWithBriefing: briefing];
[listOfViewControllers addObject:briefingViewController];
[briefingViewController release];
}
[listOfViewControllers addObject:alertViewController];
//add archives tab
NSString *archiveURL = [NSString stringWithFormat: ARCHIVEURL, DeviceID()];
UIViewController *archiveViewController = [[WebViewController alloc] initWithURL:ARCHIVEURL andTitle:#"Archives" andImage:#"archive_icon.png"];
[listOfViewControllers addObject:archiveViewController];
[archiveViewController release];
}
NSArray *oldlistOfViewControllers = [self.tabBarController viewControllers];
UIViewController *vcOld = [oldlistOfViewControllers objectAtIndex:[oldlistOfViewControllers count] -1];
[listOfViewControllers addObject:vcOld];
[self.tabBarController setViewControllers:listOfViewControllers
animated:YES];
}
My best guess is that it has nothing to do with tab bar controller. When you did not release the array, the controllers in the array would never be dealloc and there was no problem at all. So it's likely that the problem might come from deallocation of your WebViewController.
It looks like what you are creating here - listOfViewControllers - should be an instance variable of whatever object you are making here. Then you should alloc/init it inside the object's -init method, and release it in dealloc.
It is good practice (and usually necessary) to make an instance variable for anything you expect to exist after the end (or before the start) of a function call.
After [self.tabBarController setViewControllers:listOfViewControllers
animated:YES];, you can release your listOfViewControllers. Because tabBarController will retain this listOfViewControllers by copy policy.
You can see the UITabBarController reference about viewControllers property. This property adopts the copy policy.
#property(nonatomic, copy) NSArray *viewControllers