iPhone Memory Alert - iphone

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).

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.

Cleaning all memory leaks in ios

I have tried a lot to stop all leaks from my app. But when I am syncing large amount of data from
server then my ios application leaking memory.
Now I want to clean all leaked memory after some time of interval or you can say whenever i get call in function.
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
UIAlertView* alertobj = [[UIAlertView alloc] initWithTitle:#"Info" message:#"This Application facing memory issue." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertobj show];
NSLog(#"memory issue occur");
// Dispose of any resources that can be recreated.
}
Is there any way??
Nope, you can't do that.
I ran into a similar issue, sync data in smaller chunks and read about #autoreleasepool
Basically I sync between 500~1500 objects at a time depending on how much data is in the objects, wrapping them in the #autoreleasepool keeps memory low by getting rid of those objects as soon as I am done with them.

-[UIThreePartButton text]: unrecognized selector

I've been racking myself on this one for a while, and can't figure it out.
It is an action sheet that bookmarks a page (for a safari like app) When I hit Okay, i get the
-[UIThreePartButton text]: unrecognized selector at instance XXXX
I can't seem to step through where my pain is.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Bookmarks" message:#"Please enter the site name: \n \n \n" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
alert.center=CGPointMake(160, 50);
alert.tag=1;
UITextField *siteName=[[UITextField alloc]initWithFrame:CGRectMake(20, 70, 245, 30)];
siteName.backgroundColor=[UIColor clearColor];
siteName.borderStyle=UITextBorderStyleRoundedRect;
siteName.autocorrectionType=UITextAutocorrectionTypeNo;
siteName.delegate=self;
siteName.clearButtonMode=UITextFieldViewModeWhileEditing;
siteName.text=[[mainDelegate.sitesArray objectAtIndex:tag] objectForKey:#"webSite"];
siteName.returnKeyType=UIReturnKeyDone;
siteName.tag=2;
[alert addSubview:siteName];
[alert show];
}
}
I realized that it dies on the alert view method below it:
if(alertView.tag==1)
if (buttonIndex==1)
{
if(((UITextField*)[alertView.subviews objectAtIndex:4]).text==#""||((UITextField*)[alertView.subviews objectAtIndex:4]).text==nil)
{
Spefically on the if(((UITextField*)[alertView.subviews objectAtIndex:4])
I have 4 buttons/action on that action sheet, and the rest are good to go...
Do not try to manually traverse the view hierarchy of a UI element that Apple does not otherwise document. Doing something like [alertView.subviews objectAtIndex:4] is dangerous, because you end up having to make a blind assumption of the internal structure of a UIAlertView.
In this case, you're hitting the wrong element (a UIThreePartButton) and crashing your application with an exception. Even if you do get the index correct on where your text field is right now, there's no guarantee that Apple won't change the view number or ordering in a future OS release, suddenly causing all installations of your application to crash.
To prevent this, hold on to a reference to your UITextField so you don't need to probe the view hierarchy on a UIAlertView.
Even better, don't use an alert view for text input, but a custom modal view. Alerts really should be reserved for infrequent error displays or other critical updates. From the iOS Human Interface Guidelines:
The infrequency with which alerts
appear helps users take them
seriously. Be sure to minimize the
number of alerts your app displays and
ensure that each one offers critical
information and useful choices.
As an FYI, you're also leaking your siteName UITextField in the above code, and potentially your UIAlertView.
If you have 4 buttons per action would your objectAtIndex not be 3 instead of 4? Seems like you are getting an out of bounds exception.
Specifically objectAtIndex:4 will generate an exception if there are 4 items in the array since the last valid index is 3.

iphone app crashes due to Low Memory but works fine in simulator

Dear all, I have a navigation-based app with about 60 UIControllerViews, which is divided into 4 sections.
I have run with the following : 1. Build and analyse : bulid is successful with no complains. 2. Instruments allocation and leaks : no leaks.
However, the app crashed in iPhone or iPad but works fine in simulator. There is no crash reports but I do see LowMemory.log in the crashreporter folder.
I have upgraded my iphone and ipad to 4.2
Does anyone have ideas what could be wrong? I have been reading and troubleshooting for a week.
Is there a need to remove/release the UIControllerViews?
The app crashes simply by navigating between the views.
Thank you for any help.
My app has a root view called contentViewController and users can navigate to 4 quizzes from here.
This is the code I use to return to my root view.
- (void)goHome {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Warning"
message: #"Proceed?"
delegate: self
cancelButtonTitle:#"Yes"
otherButtonTitles:#"No",nil];
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[[self navigationController] setNavigationBarHidden:NO animated:YES];
if (buttonIndex == 0) {
NSArray * subviews = [self.view subviews];
[subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
self.view = nil;
if (self.contentViewController == nil)
{
ContentViewController *aViewController = [[ContentViewController alloc]
initWithNibName:#"ContentViewController" bundle:[NSBundle mainBundle]];
self.contentViewController = aViewController;
[aViewController release];
}
[self.navigationController pushViewController:self.contentViewController animated:YES];
}
else {
}
}
The simulator isn't going to give you any useful information about memory warnings—your app, running there, effectively has access to all the memory the system's willing to give it. The device is where you need to be testing for memory usage, and if you're getting warnings and crashes, then you need to do some Instruments work to figure out where you can free up some of that memory.
Look at your xcode console. If you are getting a number of low memory warnings, then you need to be allocating and de-allocating your views on the fly because they are taking up too much memory on the device (the simulator isn't quite so memory restricted).
But it could be about a million other things causing your crash. Make sure you're doing a debug build (breakpoints on) so the debugger will kick in and hopefully you can see where on the stack your crash is occurring.
You have some good suggestions already. However I'd suggest spending a lot of time reviewing XCode's debugging tools documentation. This so you have a basic understanding of what they are capable of and how to use them. Follow that up with some reading on iOS memory management, auto release pools and the like.
For your app you need to realize that there is no swap space on iOS devices. So you are forced to manage memory to an extent that you mat not have to on other platforms. Generally that means you don't want to keep to much view data in memory if it can be avoided.
In the case of the current iPad there may only be about 110MB of RAM available to the app. Specific numbers probably are iOS version dependent. In any event you need to get an idea as to how large the data structures (in memory) are for your various views. 60 different views could be considered a lot depending upon memory usage, if you don't manage it correctly you are likely to run out very quickly. This not like programming in Java or other garbage collected language.
Lastly; even though this sounds like a memory management issue it could always be something else. If you still have trouble you will need to post code. Right now it is really guess work on our part. Just remember you do not have VM and there is no garbage collection.
You are using up memory, always remember if you allocate memory you must release it, in some cases you can use autorelease so you dont forget to release it after the void dealloc method before end.

How to Prevent Multiple UIAlertView Alerts from Popping Up at Once?

My tabbar application has three tabs, each with its own navigational structure. Several of the views throughout my app load data via web service calls. These views register this notification in order to know when the app becomes active, so that they can reload the data:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadView) name:UIApplicationDidBecomeActiveNotification
object:NO];
When the app becomes active, these views all try to reload their data; however, if there is no Internet connection, the errors are caught and a UIAlert is shown to the user. The problem is that if 3 of these views are trying to reload data, 3 alert messages pop up.
How do I prevent multiple alerts from popping up to the user?
I appreciate all your thoughts, ideas, and suggestions!!
Thanks!
Brad
Edit: I tried putting this in my appDelegate, but even using this method, I seem to get multiple popups.
-(void)displayAlertWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:#"Cancel" otherButtonTitles:#"Retry",nil];
[alert show];
[alert release];
}
Keep track of whether a alert is currently being displayed (or has been dismissed recently). There really isn't another way.
If you stick the functionality in your app delegate, then you can just do something like [(MyAppDelegate*)[UIApplication sharedApplication].delegate displayNetworkFailureDialog].
EDIT: Note that some people may frown on sticking random global cruft in your app delegate...