UIAlertView -show causing a memory leak - iphone

I'm relatively new to iPhone Development, so this may be my fault, but it goes against what I've seen. :)
I think that I'm creating a UIAlertView that lives just in this vaccuum of the 'if' statement.
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(!data)
{
// Add an alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to contact server"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
NSLog(#"retain count before show: %i", alert.retainCount);
[alert show];
NSLog(#"retain count before release: %i", alert.retainCount);
[alert release];
NSLog(#"retain count after release: %i", alert.retainCount);
return nil;
}
However, the console logs baffle me.
retain count before show: 1
retain count before release: 6
retain count after release: 5
I've tried also adding:
alert = nil;
after the release. That makes the retain count 0, but I still show a leak. And if it helps, the leak's Responsible Frame is UIKeyboardInputManagerClassForInputMode. I'm also using OS 4 Beta 3.
So anyone have any ideas how a local UIAlertView's retain count would increment itself by 5 when calling -show?
Thanks for your help!

This makes some sense if you realize that [alert show] doesn't immediately put the alert up on screen. I think what happens is that the [alert show] adds the alert to some queue somewhere in the system which retains it. It won't actually be shown until you return from this function and get back to the event loop. When it eventually gets dismissed those retain counts will get decremented and it will be released then.
If you were to log messages from UIAlertView's delegate routines, such as didPresentAlertView, I'll bet that doesn't happen until after your function ends, after you've "released" the alert. Release doesn't always mean deallocate, it is just relinquishing ownership. It only causes a dealloc if there are no owners left.

I highly doubt this is a memory leak. The alert view is just getting shown: it is getting added to the window, etc: which all retain what they own. I bet you that if you check once it has been closed, it won't exist anymore.

My guess would be that this is related to the beta sdk. There are many errors/bugs in the betas. I would suggest checking it with the 3.1.3 or 3.2 sdk.

Related

UIAlertView memory issues

I have created a very simple iPhone application, with single view and a UIButton with action to show UIAlertView.
I am using following code
- (IBAction)showAlert:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
Instruments allocations tool screen shot is attached.
In the image,low memory allocations shows app running without showing UIAlertView, and high peaks shows memory usage after i have shown UIAlertView, even i have dismissed UIAlertView and release it but it continues to show same memory state and living objects (as high as 50,000). but when i press home button app goes in background and you can see in attached image living objects and used memory decrease.
Questions:
Whats wrong with my code?
Why even after releasing UIAlertView it shows high memory allocation and living objects?
Why i have to go to background to release memory and living objects?
I would not worry too much about it, unless this is the major memory bottleneck in your app, or unless each UIAlertView cumulatively adds more memory.
Your code is correct. But even though you release the UIAlertView, the user interface system holds on to it at least until you dismiss the alert. In addition to the UIAlertView itself, it also allocates graphics resources needed to show the alert. After you dismiss the alert, it depends on when the autorelease loop kicks in, and on caching parameters, whether and when the memory gets released.
When you push the home button, then your application goes to the background, and as part of that memory deallocation is forced. That is, caches are emptied, autorelease cycle is run, etc.

UIAlertView in ARC app

I have iphone sample application with one button. On tap it calls code:
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"test"
message:#"test"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
Application has ARC enabled.
The problem is that if I click on OK button in alert, application crashes with EXC_BAD_ADDRESS - probably because of alert is already removed by arc.
What is recommended way to solve this? without adding property to viewcontroller
thanks
My guess is either you haven't implemented the UIAlertViewDelegate methods or that self has gone out of scope.
If you don't care about being alerted when someone dismisses the alert box, change the delegate to nil.
e.g.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"test"
message:#"test"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
The delegate property of UIAlertView is declared as a weak reference (indicated by the assign keyword). This means ARC will not increment the retain count and you will need to retain a reference to the delegate object (whether it is self or a separate object). This reference should be maintained for the full life of the UIAlertView.
#property(nonatomic,assign) id /*<UIAlertViewDelegate>*/ delegate; // weak reference
I assume that the reason for this is to prevent a loop and failure to release as in the common case the object creating the UIAlertView will retain a reference to it and be it's delegate so closing the loop and preventing release.
This is probably a common pattern for delegates but I hadn't realised until I hit exactly the same issue. I ran in the simulator with zombie detection enabled and it clearly indicated the reference counts and I saw that it was not being retained by the UIAlertView. That was when I checked the header file.
The answer to this question provides some additional information about delegates on system classes and the assign keyword.
iPhone ARC Release Notes - dealloc on system classes delegates?

UIAlertView and cocos2d memory mangement

I display a UIAlertView above my cocos2d layer.
I release it after I how it.
Is it really gone? Do I have to somehow remove it from my UIView?
If you just do
UIAlertView* alert = [[UIAlertView alloc] initWithTitle...];
[alert show];
[alert release];
then there's no need to worry about it. However, if you set the alert's delegate to some object, make sure that object still exists when the user taps a button in the alert - otherwise your app will crash when the alert will try to call alertView:didDismissWithButtonIndex: delegate method.

iOS4 (UIAlertView) why this code causes memory leaks?

suppose you create a new iOS app from scratch, with just one single window.
then you put this code in the appDelegate application didFinishLaunching method :
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:#"alert"
message:#"message"
delegate:nil /* same problem with 'delegate:self' */
cancelButtonTitle:nil
otherButtonTitles:#"Ok", nil];
[myAlert show];
[myAlert release];
build and run in simulator 4.1, attach instrument, and...
this causes each time a memory leak.
in simulator 3.1.2 on leopard, no problem at all.
Of course, in a real app, the UIalertView is trigerred by a button, but the result is identical.
What is the problem ?
is UIAlertView buggy until iOS4 ?
Don't check for leaks in a simulator. It doesn't have the same memory model so reports leaks when there aren't any.
Test on a real device and if the leak is still there, report it as a bug to Apple :)

iPhone Memory Alert

I have read about this function didReceiveMemoryWarning that actually hasn't really helped.
I would like to show a UIAlert View to tell the user that the action he is about to take will lead to problems with memory.
So apart from crashing, which is a nasty way to inform the user that there is a memory Warning received, is there a possible implementation of a UIAlertView?
In your application delegate class (eg MyApplicationAppDelegate.m) implement the didReceiveMemoryWarning method:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
// Show an alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Running low on memory"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Pheelicks did give you a good answer to your question, but this is definetly not what you want to do. When you receive this warning, you are already in low memory condition. What you want to do when you receive this warning is release as much memory as possible. Like large images that you might be keeping in memory, large arrays of string or any other large object. Instruments will help you alot in finding the culprits.
Also, you also want to implement didReceiveMemoryWarning on any view controller that allocates alot of memory so they can do some cleanin up there also
Hopes this helps :)
the action he is about to take will
lead to problems with memory
If there is some action you know of the user taking that will lead to memory problems, you should keep them from taking that action, or just warn them yourself when they are about to take the action (with an alertview).