This is a very simple issue but I have no idea why it's happening. In my header file, I've declared a UIButton *leftButton. In the viewDidLoad method I do this leftButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];
Then in some other method I have:
leftButton.frame=newFrame;
leftButton.tag=i;
[leftButton addTarget:self action:#selector(leftButtonSelected:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:leftButton];
However I keep getting a crash when the above method is called. Sometimes I get a message, other times it just crashes with no message. I can't really replicate any crash messages, now all I'm getting is just a general crash, but it kept crashing from weird issues such as [UIGestureRecognizer setFrame] is causing problems or [WebView setFrame] or something..for some reason it keeps thinking that leftButton is something else than a UIButton, but this is not the case. There is nothing else named leftButton in my entire project. Any ideas?
Your first method is returning an autoreleased object, most likely it has been released by the time your second method is called. Either retain the button in the first method or use a retained property to hold on to it rather than an ivar.
Also, remember to release this in your dealloc method at the end.
Related
In my iPhone/iPad app,
I am adding one subview to my main view.
This subview has one imageview and button.
When to release them ?
My code is here,
customAlertView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 600)];
UIImageView *imgv=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"celebration.png"]];
UIButton *btnOK=[UIButton buttonWithType:UIButtonTypeCustom];
[btnOK setTitle:#"OK" forState:UIControlStateNormal];
[btnOK addTarget:self action:#selector(alertOKClicked) forControlEvents:UIControlEventTouchUpInside];
[customAlertView addSubview:btnOK];
[customAlertView addSubview:imgv];
[self.view addSubview:customAlertView];
[imgv release];
[btnOK release];
In one another method I am writing the code.
[customAlertView removeFromSuperview];
My confusion is imageview and button is there If
I release the customalertview here will it releases its subviews automatically.
If yes then no problem.
If NO how to release it
as I have done here released the objects immediately after adding subviews.
It will cause my OK button Unworthy. And will not affect the button click.
So, On removing from superview should I write.
[[customalertview subviews] release];
Your code is correct.
You release them after you've added them to the alert view, as the alert view takes care of retaining them. When you call removeFromSuperview, it'll get released automatically.
I think the points you are missing, based on your comments on the existing answers, are the following:
A view retains its subviews - so if you create a new view object, and add it as a subview to something else, you can then safely release it, unless you'd like to keep a reference around for it yourself.
When a view is removed from its superview, it is released. So if there are no more objects retaining it, it will be deallocated.
When a view is deallocated, it will automatically release all of its subviews, and so on down the tree.
Enable ARC as soon as you are able to.
You are doing it the right way. The customalertview will releases its subviews automatically.
Your object will be released when the release count go to 0, that means in the theory, and if you are coding well, that this object does not have any reference to it anymore.
While you maintain your custom alertView in your view, you have an object retaining your things, so the release count will not be 0 until you remove the customAlertView, because you have added they to the customAlertView, and when you remove the alert, the alert will be released, and all the things that it is retaining will be released too.
Hope it help you to understand how things work.
If you want to know more about memory management you can take a look at apple documentation here
EDIT:
I forgot to mention that you will need to release your custom alert too after you remove it.
If you do not understand the memory management you also can take a look at: http://cocoadevcentral.com/d/learn_objectivec/ section 7
I believe I have to release an object if I created it with the keywords init, alloc, copy, or move I believe. I may create objects with code that don't use this keywords so I guess I don't have to release them right? so take for instance this code:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Hello" forState:UIControlStateNormal];
button.frame = CGRectMake(40.0, 200.0, 170.0, 40.0);
[self.view addSubview:button];
since I did not use any of those keywords in my code I should not release it right? so when is that object being released? I am little confused with the memory managment stuff.
The only object you created here is the UIButton, and you used the buttonWithType class method. That is returning you autoreleased object, so you don't have to release it.
Keep in mind though that if you were to need this button at a later time you would need to retain it and eventually release it. Because you add this button to a view, the view retains a copy in this case so again you don't need to worry about it.
If you're running XCode 4 I recommend running the 'analyze' mode to run quick basic check for memory leaks... that looks fine (your code).
You are absolutely correct in that you don't have to explicitly release anything that you don't take ownership of via alloc, copy, new, or retain.
In this case, you've created the button via a convenience method (buttonWithType:). This returns an autoreleased UIButton object. This is released automatically when the autorelease pool is flushed at the end of the run loop.
There's nothing for you to worry about here. Let the runtime take care of it.
There is an NSAutoreleasePool that manages the memory for you. You were correct about alloc and copy (alloc and init are usually together) but not move. Another one that returns a retained object is methods prefixed with new ex. +(id)new;. An auto release pool is required for each thread to manage memory for each event loop.
An example of how a button implementation may look
-(id)buttonWithType:(UIButtonType)type
{
UIButton *button = [[[UIButton alloc] initSecretlyWithType:type] autorelease];
//Customize button if needed
return button;
}
See Using Autorelease Pools for more details.
I kind of understand why I'm getting this analyzer warning. Because I'm using an object that is being passed in. I've tried autorelease and retain however these cause me other problems like unrecognized selector sent to instance.
The aim of my CommonUI function is to re-use code, but I have to cater for addSubView and presentModalViewController.
Perhaps I'm doing some obvious wrong ?
Change your code like this:
HelpViewController *helpvc = [[HelpViewController alloc] init....];
[vw addSubview:helpvc.view];
[helpcv release];
I think you don't need to pass the other VC.
There are two problems here.
First, if you call [vc release] (as the other answers suggest), you'll certainly make the analyzer happy but likely crash the app. A view controller's view doesn't retain the controller, so any button targets in the view will be pointing to garbage.
You will need to somehow keep the HelpViewController retained for as long as it is showing up onscreen. The "parent" view controller should likely retain it somehow. You could autorelease it, and return it. Then whomever calls showHelpClick... would retain the returned controller.
Second, you don't need to have the (UIViewController *)vc passed in as an argument.
I have below code in a IBAction linked to a UIButton to change the background image on Button Click.
UIImage *imageGreen=[UIImage imageNamed:#"bgGreen.png"];
[clickButton setBackgroundImage:imageGreen forState:UIControlStateNormal];
[imageGreen release];
after clicking the button three times it crashes the app in iPhone Simulator 4.0. I am alreading releasing the imageGreen object, what else can i do to prevent this.
No, you should not release imageGreen.
This variable is received with a convenient method, thus will autorelease itself. Calling -release will cause double-release error and crash the program.
Please read the memory management guide.
I want to add a button on a view dynamically. Here is the code.
UIButton *x=[UIButton buttonWithType:UIButtonTypeRoundedRect];
Here, I have not used "alloc" function.
The questions for this statements are as follow.
If we are using imageview for the same situation, we have to create an temp imageview add to your current view and release it. What to do for button?
How are buttons allocated and de-allocated?
If buttons are allocated? How it's memory is been managed?
Now when I use [x release]; - is it right or wrong?
No alloc/init or new so it will be autoreleased when it is no longer needed. When you add it to the UIView the count is increase and retained by the view, then also released when the view is released.
You do not need to call release in this case. Since you are using a convenience constructor, the object that is returned is an autoreleased object.
If you use an alloc / init form, you are responsible for releasing the object.
UIButton *x=[UIButton buttonWithType:UIButtonTypeRoundedRect];
using this method u cant relese the button
instead of use
UIButton *x = [[UIButton alloc]init];
and then release