iphone SDK: UIView dealloc not called. Why? - iphone

I have a custom UIView called TiledImage which has a single property named tiledImage and a custom drawRect method. I add this view to my ViewController, but when the ViewController is deallocated the dealloc for this view is never being called, even though I am releasing the view and setting it to nil. What could be causing this? I don't have any other references to the view, so my understanding is that it should release correctly.
This is how I add the view to my view controller:
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"tile" ofType:#"png"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imagePath];
self.backImageView = [[TiledImage alloc] initWithFrame:IMAGE_FRAME];
self.backImageView.tiledImage = image;
[self.view addSubview:self.backImageView];
[self.view sendSubviewToBack:self.backImageView];
[image release];
And in my ViewController's dealloc method I have this:
_backImageView.tiledImage = nil, [_backImageView release], _backImageView = nil;
That line of code is hit, but dealloc is never called on TiledView. Note that _backImageView is the var that the property backImageView uses.
Can someone give me ideas on what I may be doing wrong that is preventing the dealloc on the TiledImage object from being called?

If self.backImageView is a retain property, you have a memory leak - the TiledImage has a retain count of 1 prior to invoking the setter, 2 afterwards.
Your code for adding the view should look like e.g. the following instead:
TiledImage *imageView = [[TiledImage alloc] initWithFrame:IMAGE_FRAME];
self.backImageView = imageView;
[imageView release];

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.

Iphone: Does a custom made UIView needs a dealloc

I have a custom made uiview class, and i have a dealloc with other releasing call within it.
In this custom uiview, I have 3 outlet of controls : buttons, textview etc. When the custom uiview deallocated, I received this error: Error for object 0x88782c0: pointer being freed was not allocated.
Inside the code, I have not release any of these outlet at all. When I removed those 3 outlet of release call, the error was gone. Do I need to deallocate those outlets.
[[[[NSBundle mainBundle] loadNibNamed:#"ParanoidView" owner:self options:nil] objectAtIndex:0] autorelease];
[self.view setFrame:CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height)];
[self addSubview:self.view];
The above code is add within the initWithFrame call to load the nib file.
There are many things wrong with your code.
[[[[NSBundle mainBundle] loadNibNamed:#"ParanoidView" owner:self options:nil] objectAtIndex:0] autorelease];
You cannot release or autorelease something you didn't retain. Period.

releasing a UILabel in dealloc crashes the app after it was retained, allocated & autoreleased

I have a UILabel in my class header file defined as :
`#property (nonatomic, retain) UILabel *label1;`
and it exists as instance variable like this:
`UILabel *label1;`
and synthesized in the .m file, however, in viewDidLoad method I do:
`label1 = [UILabel alloc] init] autorelease];`
then I do various things on the label like setting its frame, text color, etc ...
when the view controller is deallocated, the app crashes with this message in console
(Zombies enabled): `[CALayer release] message sent to deallocated instance` ...
The app will not crash when I :
1) remove the autorelease word .. or
2) if i do not release label1 in the dealloc method .. or
3) remove [super dealloc]; from the dealloc method of the view controller.
how can I properly release this UILabel without facing such crash !!
You are doing right.Autorelease and release in dealloc.
But it shouldn't be crash.Because I did the same thing to check.
Could you please check accciendlty may be u release the label some where else.
And releasing in dealloc again.
since you have declared the label as retain. The allocation can be
UILabel *myLabel = [[UILabel alloc] init];
// set all properties of label
self.label1 = myLabel;
[myLabel release];
myLabel = nil;
And in dealloc release your label1.
[label1 release];
this is the way I'm used to and this makes things smoother for me.
the label is released already before dealloc is called. that is because its an autorelease object. your dealloc is trying to release a UIlabel that already been released, an it crashes.. in your question. you can use 1 or 2. if you allocated the object once, then call a release just once. its not because you assign retain to your property in #property directive will add 1 retain count to your object , #property(retain) will not allocate anything, but will tell the compiler how you want your properties treated
strangely enough, when I used self.label1 = [[[UILabel alloc] init]autorelease]; instead of label1 = [[[UILabel alloc] init] autorelease]; solved the problem. the dealloc method remains as is without any change. really weird !!
Do this and u will not use autorelease for label1:
- (void)dealloc
{
if(label1)
{
label1 = nil;
[label1 release];
}
[super dealloc];
}

How do I reference my MainViewController from another class?

I am building an iPhone Utility app that uses UIImageView to display an animation. Within the MainViewController's viewDidLoad() method, I am creating an instance of a CustomClass, and then setting up the animations:
- (void)viewDidLoad
{
[super viewDidLoad];
cc = [CustomClass new];
NSArray * imageArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"image-1-off.jpg"],
[UIImage imageNamed:#"image-2-off.jpg"],
[UIImage imageNamed:#"image-3-off.jpg"],
[UIImage imageNamed:#"image-4-off.jpg"],
nil];
offSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
offSequence.animationImages = imageArray;
offSequence.animationDuration = .8;
offSequence.contentMode = UIViewContentModeBottomLeft;
[self.view addSubview:offSequence];
[offSequence startAnimating];
}
That works fine. However, I would like to be able to move all the above code that sets up the UIImageView into my CustomClass. The problem is in the second to last line:
[self.view addSubview:offSequence];
I basically need to replace 'self' with a reference to the MainControllerView, so I can call addSubview from within my CustomClass. I tried creating an instance var of CustomClass called mvc and a setter method that takes a reference to the MainViewController as an argument as such:
- (void) setMainViewController: (MainViewController *) the_mvc
{
mvc = the_mvc;
}
And then I called it within MainViewController like so:
[cc setMainController:MainViewController:self];
But this yields all sorts of errors which I can post here, but it strikes me that I may be overcomplicating this. Is there an easier way to reference the MainViewController that instanatiated my CustomClass?
The cleanest way to do this would be to create a subclass of UIImageView and create a customize initializer that accepts the array. So,
#interface MyCustomImageView:UIImageView {
//...
}
-(id) initWithFrame(CGRect) aRect animationImages:(NSArray *) imageArray;
#end
Then in your main view controller just initialize the custom image view, populate it and add it to the subviews. This will make everything nicely encapsulated, modular and reusable.

iPhone - Memory Management problems

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!