Objective-c:"Please wait" message when go to the next page - iphone

I am developing an app which has several viewControllers. The first one is "MainMenu" and the second one is "Page1".
I would like to show an alert says "Please wait..." when it goes to the next page. My code below is working but the alert comes up after the "page1" is loaded. I would like it to come up when a user press a button on "MainMenu" page.
Do you have any suggestions to accomplish this?
Thanks in advance.
AppDelegate.m
-(void)showAlert{
altpleasewait = [[UIAlertView alloc] initWithTitle:#"Please Wait..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[altpleasewait show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.center = CGPointMake(altpleasewait.bounds.size.width / 2, altpleasewait.bounds.size.height - 50);
[indicator startAnimating];
[altpleasewait addSubview:indicator];
}
-(void)waitASecond{
[self performSelector:#selector(dismissAlert) withObject:self afterDelay:0.8];
}
-(void)dismissAlert{
[altpleasewait dismissWithClickedButtonIndex:0 animated:YES];
}
MainMenu.m
-(void)gotoNextPage{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate showAlert];
page1 = [self.storyboard instantiateViewControllerWithIdentifier:#"Page1"];
[self presentModalViewController:page1 animated:NO];
}
Page1.m
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
-------------some methods--------------
[appDelegate waitASecond];

This is just a suggestion. I would do the following.
In Page1.m in -viewDidAppear, I would call the alert view to pop up. This is happening on the main thread. So I am not preventing UI from being displayed, or responsive.
I would move all methods that are related to loading the Page1 content, e.g. texts that are to be read from a URL, into a block, and use GCD, so that they happen in the background, and not blocking the main thread.
Once the loading is done...
I would take them, update the UI, and dismiss the alert view.
Here is a simple tutorial that may give you an idea.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial

What you could do is put the alert in the IBAction. Check when they dismiss the alert, then change views. Or use an NSTimer, assign a selector to that timer and implement that selector to change views.

Related

call presentModalViewController in block completion

in my code i'm using this class:
https://github.com/gpambrozio/BlockAlertsAnd-ActionSheets
and i want call a presentModalViewController when i press the button in the dialog view in this way:
BlockAlertView *alert = [BlockAlertView alertWithTitle:#"Example" message:#"Text"];
[alert setDestructiveButtonWithTitle:#"Ok" block:^{
FirstView *firstView = [[FirstView alloc] initWithNibName:#"FirstView" bundle:nil];
[self presentModalViewController:firstView animated:YES];
}];
[alert show];
but the app freeze, and after a minute open the view, so my question is how i can presentemodalviewcontroller in block completion?
Actually have some mistakes, first, when you instanciate some class / variable inside a block they responde and have life cycle just inside that block.
So your block you run in another thread and this is the cause, and with this way you probably will cause retain cycle that its very bad situation for you app, change for something like this:
BlockAlertView *alert = [BlockAlertView alertWithTitle:#"Example" message:#"Text"];
FirstView *firstView = [[FirstView alloc] initWithNibName:#"FirstView" bundle:nil];
__weak typeof(self) weakSelf = self;
[alert setDestructiveButtonWithTitle:#"Ok" block:^{
[weakSelf presentModalViewController: weakSelf.firstView animated:YES];
}];
[alert show];
Doing this, using __weak typeof we created a weak reference that prevent blocks from create strong reference cycle *(its good to read about) and now we make sure that will use our view that are instantiated for present new modal view.
Any doubt fill free for ask :)

MBProgressHUD display messages one over the other

In the viewDidload method, i am using MBProgressHUD to show an activity indicator until data is downloaded from the net, and thereafter to check if the application has enabled GPS. based on this i alert the user using MBProgressHUD.
My code;
ViewDidLoad
hudForDownloadData = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view hudForDownloadData ];
hudForDownloadData .delegate = self;
hudForDownloadData .labelText = #"Loading";
hudForDownloadData .detailsLabelText = #"updating data";
[hudForDownloadData showWhileExecuting:#selector(downloadDataFromWebService) onTarget:self withObject:nil animated:YES];
[self downloadDataFromWebService]; // This method is called, and then data is downloaded from the webservice, once the data is downloaded i will remove the `MBProgressHUD ` alert
Now i am checking if the application has enabled access to GPS, and alert the user if not.
hudForGPS = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
hudForGPS .delegate = self;
hudForGPS .labelText = #"Loading";
hudForGPS .detailsLabelText = #"updating data";
[hudForGPS showWhileExecuting:#selector(checkIfApplicationEnabledGPS)
onTarget:self withObject:nil animated:YES]; // This will only take a
maximum of 2-3 seconds. and i will remove it after that
The problem is that; when the internet/wifi is down, the hudForDownloadData will continuously animate (display uiactivityindicator). In the meantime hudForGPS will also execute. But it will display below hudForDownloadData . So the user will not be able to see it.
What i want to do is to execute the checkIfApplicationEnabledGPS first, and wait till its alert finishes (it will only take 2-3 seconds), and then load execute the downloadDataFromWebService where if the internet/wifi is not available it will display forever.
How can i do this programatically ?
Execute checkIfApplicationEnabledGPS first and when it is finished,you show an alert box,If you are using UiAlertView to show the alert then you can handle it's delegate:-
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
when the user presses ok button in UiAlert view you can override the above delegate with hudForDownloadData
In this way both the checkIfApplicationEnabledGPS and hudForDownloadData will be executed one after the other

Can't see my alertView unless I comment out automatic dismission

I am implementing a simple alert view with activity indicator to show to the user while the app is performing the restore of the database. Everything is fine except that I can't see the alert view, unless I comment out the automatic dismiss line (last one here).
Ok, the restore of the database is quite quick, but still I would expect to see it even if for an instant, no? I can see the screen get's a little darker during animation but that's all. I also tried putting a for loop to extend the time, the time extends but still no alert view.
There is nothing wrong in the way the alert view is called, since if I comment the dismiss, I can see it...only forever. Anyone has an idea here?
Before anyone says it, I tried changing the delegate of the alertView to self as posted here, but it didn't help.
// First we prepare the activity indicator view to show progress indicator
UIActivityIndicatorView * activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[activityView setFrame:CGRectMake(121.0f, 50.0f, 37.0f, 37.0f)];
[activityView startAnimating];
// Then we put it in an alert view
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Loading" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
[alertView addSubview:activityView];
[alertView show];
// Finally we operate the restore
[[SQLManager sharedSQL] restoreDatabase:[restoreDatabaseURL path]];
// And we can dismiss the alert view with the progress indicator
[alertView dismissWithClickedButtonIndex:0 animated:NO];
Im not sure why this happens, but I encounter it occasionally as well. One way I have gotten something like this to work is by using performSelector:withObject:afterDelay: on the next call, like this:
// First we prepare the activity indicator view to show progress indicator
UIActivityIndicatorView * activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[activityView setFrame:CGRectMake(121.0f, 50.0f, 37.0f, 37.0f)];
[activityView startAnimating];
// Then we put it in an alert view
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Loading" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
[alertView addSubview:activityView];
[alertView show];
// Finally we operate the restore
// [[SQLManager sharedSQL] restoreDatabase:[restoreDatabaseURL path]];
[[SQLManager sharedSQL] performSelector:#selector(restoreDatabase:) withObject:[restoreDatabaseURL path] afterDelay:0.25];
// And we can dismiss the alert view with the progress indicator
[alertView dismissWithClickedButtonIndex:0 animated:NO];
performSelector Documentation
Sounds like it's dismissing itself almost instantaneously. If you add a for loop, it will likely freeze all other computations which means your activity view won't show up until the loop breaks.
You could try using a NSTimer to call another function to determine if the restore is complete or not;
// Setup our the timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(checkRestore)
userInfo:nil
repeats:YES];
// Timer function checking for completion
-(void)checkRestore {
if (restore is complete) {
[alertView dismissWithClickedButtonIndex:0 animated:NO];
}
}

Show UIAlertView on splash screen

I used to show a splash screen which in background load some data from web, I also check that if the location of the user is changed from one city to another city I want to show in alert to the user with the message that you are now in "CityName" would you like to see data from this city?
I have tabbed application and I have presented the splash screen as follow in the app delegate class.
SplashViewController *controller = [[SplashViewController alloc] initWithNibName:nil bundle:nil];
tabBarController.view.frame = [[UIScreen mainScreen] bounds];
controller.tabBarController = self.tabBarController;
[application setStatusBarStyle:UIStatusBarStyleBlackOpaque];
[window addSubview:controller.view ];
//[window addSubview:tabBarController.view ];
[self.tabBarController presentModalViewController:controller animated:YES];
[window makeKeyAndVisible];
[controller release];
Now when I show the alert screen it crash the application with "EXC_BAD_ACCESS" message and the stack trace show that _buttonClick is released in UIAlertView class.
Please advise what should I do, I also tried with UIActionSheet but the same problem with this thing too.
I think there is some problem with the model thing with the current view (SplashView).
Thanks in advance.
Are you trying to display your UIAlertView inside of your SplashViewController viewDidAppear? If not, I would try that first. I would also make sure you have your UIAlertView clickedButtonAtIndex method setup properly to try and trap what is going on.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Your Location Has Changed"
message:#"Your location has changed since you last opened opened THEAPP. Would you like to refresh your data?" delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alert.tag = 1;
[alert show];
[alert autorelease];
Then for the clickedButtonAtIndex method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
//--NSLog(#"You clicked button #%i",buttonIndex);
if (alertView.tag == 1){
if (buttonIndex == 0) {
//--NSLog(#"CANCEL");
} else if (buttonIndex == 1) {
//--NSLog(#"OK");
}
}
}
Doing all of this on a splash screen should be fine as long as you take into account the HIG's requirements for using the users location. Hope this helps!
I resolve this issue, the problem was that my Splash View was a modeled view and invoked by
[self.tabBarController presentModalViewController:controller animated:YES];
what I did that I shifted the data downloading to another view controller and there I can show alerts, and can handle that

UIAlertView shows up twice

My alertview appears twice and requires 2 user clicks to dismiss.
- (void) showAlert: (NSString *) message
{
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"You chose"
message: message
delegate: self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok",nil];
av.tag = SLIDER_ALERT;
[av show];
}
I am then releasing the alertview in the delegate method "alertView: (UIAlertView *) alertView clickedButtonAtIndex: (int) index"
I suspect the problem is that I have built my own view hierarchy programmaticaly. I have one parent view for the viewcontroller. Under that i have 2 other views (parentView -> subview1 and subview2). I've tried to call [self.view addSubview: av] but that does not work. Neither does bringToFrontSubView:
Any help would be much appreciated
Peyman
The Alert code is fine (other than the release, mentioned in the comments).
[av show] is all that's required to show a view. You don't add UIAlertViews as subviews.
Call it after a delay of 0.1 sec [self performSelector:#selector(showAlert:) withObject:nil afterDelay:0.10];
Hope this will solve your problem.
With using autorelease the Alert View seems to be twice or 3 times. And for iOS4 it needs to be autoreleased otherwise it will crash.