Change UIAlertView message - ios

I have a problem with UIAlertView message, I need to change alert message with loop
First,
I declare this in implementation
NSString *alertMessage;
UIAlertView *theAlert;
and
- (IBAction)doSearching:(id)sender
{
theAlart = [[UIAlertView alloc] initWithTitle:nil message:#"Searching..."
delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[theAlart show];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(searchAfterAlertShow) userInfo:nil repeats:NO];
}
- (void)searchAfterAlertShow
{
for (int i = 0; i < [dataArray count]; i++) {
alertMessage = [NSString stringWithFormat:#"Searching... (%d/%d)"
, i, [dataArray count]];
NSLog(#"%#", alertMessage);
// do something here
if (i == [dataArray count]) {
[theAlart dismissWithClickedButtonIndex:0 animated:YES];
}
}
}
and in Alert delegate
- (void)didPresentAlertView:(UIAlertView *)alertView
{
[theAlart setMessage: alertMessage];
}
The Log is writing:
Searching... (1/8)
Searching... (2/8)
...
Searching... (8/8)
but the alert message changed at the end of loop

If the operations are too fast, the dismiss animation will take longer than the loop itself.
Most UI animations are async, therefore they happen in the background and they don't wait. you can either delay the operation to compensate for the animation duration, or pass NO for animated parameter in dismissWithClickedButtonIndex:animated

Related

How to redirect to home page after SCLAlertView showWaiting alert?

I would like to show a SCLAlertView alert and after few seconds, it will disappear and redirect to other viewcontroller. But now what i did is after click on "Done" button, the action only can be executed. Any idea? Please help.
Here is my code:-
-(IBAction)submitButtonDidPressed:(id)sender {
NSString *userName = [NSString stringWithFormat:#"Welcome back %#", txtUsername.text];
SCLAlertView *alert = [[SCLAlertView alloc] init];
[alert addButton:#"Done" target:self selector:#selector(clickLogin:)];
alert.customViewColor = ThemeBlueColor;
[alert showWaiting:self title:#"Welcome" subTitle:userName closeButtonTitle:nil duration:2.0f ];
}
-(void) clickLogin:(UIButton*)sender
{
int index = 0;
self.tabBarController.selectedIndex = index;
[self.tabBarController.viewControllers[index] popToRootViewControllerAnimated:NO];
}
You can use alertIsDismissed to call navigation like this:
-(IBAction)submitButtonDidPressed:(id)sender {
NSString *userName = [NSString stringWithFormat:#"Welcome back %#", txtUsername.text];
SCLAlertView *alert = [[SCLAlertView alloc] init];
[alert addButton:#"Done" target:self selector:#selector(clickLogin:)];
alert.customViewColor = ThemeBlueColor;
[alert showWaiting:self title:#"Welcome" subTitle:userName
closeButtonTitle:nil duration:3.0f ];
[alert alertIsDismissed:^{
[self clickLogin:nil];
}];
}

xcode UIAlertView on an NSTimer

I want to put an alert view on a 15 minute timer with a YES or NO button. This works fine if the user stays on that view. However the UIAlertView uses a local variable for its title and in the delegate method. When the user changes views the program crashes. Can I make a UIAlertView wait for 15 minutes then implement the delegate method? I tried to put the delegate method in other views, but don't know how to pass the variable with the alert. I've done a little research and think maybe with a Notification or background thread (but background threads I don't think can do UI stuff and an alert is UI)
- (IBAction)sendInAppMsg:(UIButton *)sender
{
....
//****This is the message that calls the UIAlertView on a timer
[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(pause) userInfo:nil repeats:NO];
}
-(void) pause
{
UIAlertView *responseAlert = [[UIAlertView alloc] initWithTitle:#"Success?" message:[NSString stringWithFormat:#"Did you reach %# %#", self.currentDoc.firstName, self.currentDoc.lastName ] delegate:self cancelButtonTitle:nil otherButtonTitles:#"Yes", #"No", nil];
[responseAlert show];
}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//Update Parse Cloud with users response
PFObject *contactAttempt = [PFObject objectWithClassName:#"ContactAttempt"];
contactAttempt [#"inApp"] = #"push";
contactAttempt [#"from"] = [[PFUser currentUser] username];
contactAttempt [#"to"] = [NSString stringWithFormat:#"%# %#", self.currentDoc.firstName, self.currentDoc.lastName ];
if (buttonIndex == 0) {
contactAttempt [#"response5"] = #YES;
[contactAttempt saveInBackground];
}
if (buttonIndex == 1)
{
contactAttempt [#"response5"] = #NO;
[contactAttempt saveInBackground];
}
}
//works fine and updates cloud with user response unless user changes views :(

how to do things between two UIAlertView (ios7)

I define a UIAlertView, its tag = 101, to determine save or not, show another UIAlertView called alertView2 when clicked save button, and then delete the subviews of rootView. But when I call clear Code [self clearAllSubviewsInRootView];here, it clear subViews before call alertView2. How do I fix it?
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 101)
{
if (buttonIndex == 0)
{
}
else
{
if (buttonIndex == 1)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
alertView.tag = 102;
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show];
}
[self clearAllSubviewsInRootView];
}
}
if (alertView.tag == 102)
{
if (buttonIndex == 0)
{
}
else
{
NSArray *viewArray = [self.canvasView subviews];
NSUserDefaults *UD = [NSUserDefaults standardUserDefaults];
NSString *scaleStr = [UD objectForKey:#"scale"];
NSArray *dataArray = [NSArray arrayWithObjects:scaleStr, _labelArrivalTime.text, _textAccidentLocation.text,
_textDeclare.text, _textWeather.text, _textRoadSurface.text, [NSNumber numberWithFloat:canvasSize], nil];
NSMutableArray *array = [NSMutableArray arrayWithObjects:viewArray, dataArray, nil];
NSData * encodedata=[NSKeyedArchiver archivedDataWithRootObject:array];
NSString *fileName = [alertView textFieldAtIndex:0].text;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *floerName = #"file";
NSString *saveDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:floerName];
NSString *filePath = [saveDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.rta", fileName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"file existed" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
alertView.tag = 103;
[alertView show];
}
else
{
[encodedata writeToFile:filePath atomically:YES];
[self saveImage:_prospector.image :filePath :#"勘查员"];
[self saveImage:_draftman.image :filePath :#"绘图员"];
[self saveImage:_person.image :filePath :#"当事人"];
}
}
}
}
UIAlertViews are modal views, but that does not mean they are synchronous.
In fact, UIAlertViews are asynchronous modal views.
In plain english, that means that they will be presented on screen, but some other code may be executed simultaneously (= asynchronous). So, code execution does not stop after calling [myAlert show]. The user however, is not able to select something else, he or she must deal with this one and only element on screen (= modal).
Having said that: I do not know the exact implementation of UIAlertViews, but it would not surprise me if the current runloop is being run to the end until the alert is actually presented on screen. That means, all code after [alertView show] will be executed to the end, and only then the alert will show (with the next runLoop).
So, you are asking "why it clears subviews before showing the second alert", but this is exactly what you tell it to do:
if (buttonIndex == 1)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
alertView.tag = 102;
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show]; // <-- you show the alert
}
[self clearAllSubviewsInRootView]; // <—- and clear all views
You are creating and showing the second view and then immediately call [self clearAllSubviewsInRootView] after [alertView show].
If you want to clearAllSubviews only after the user has selected something in the second alert view, you must move this call [self clearAllSubviewsInRootView]to a later point in your if (alertView.tag == 102) routine
The main problem here js you override name of the alertView inside method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
You have here property named alertView. Later you declare:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
This is a bit confusing and i'm not sure what are you trying to achieve here.
But GCD seems to fitting your problem so Apple provide here a useful snippet (you can call it by start writing dispatch_after):
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//put code here, whatever you want to fire later (after two seconds in this case)
});
In your case you probably want (i'm not sure) to keep second alert view after code is completed. In this case you should
This works for me,.. And it so simple you can use this for an infinite alertview.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([alertView.title isEqualToString:#"First Alertview Title"]) {
if (buttonIndex == [alertView cancelButtonIndex]) {
// do your stuff in cancel button --->First Alert
} else if (buttonIndex == 1) {
// do your stuff in other button ----> First Alert
}
} else if ([alertView.title isEqualToString:#"Second Alertview Title"]) {
if (buttonIndex == [alertView cancelButtonIndex]) {
// do your stuff in cancel button ----> Second Alert
} else if (buttonIndex == 1) {
// do your stuff in other button -----> Second Alert
}
}
}

NSOperaionQueue and UIAlertView

The problem is that if I create and display two alert - the second will override the first, and after it closed displayed first. So not pretty.
I'm trying to create a queue alerts with NSOperationQueue. That you could add a few alerts and they show a sequence to close. But I can not do so would be that I add operations are performed sequentially, waiting for the previous one. They are executed in parallel.
AlertOperation.h
#import <Foundation/Foundation.h>
#interface AlertOperation : NSOperation<UIAlertViewDelegate>
#property (nonatomic,assign) BOOL isFinishedAlert;
- (AlertOperation *)initWithAlert:(UIAlertView *)alert;
#end
AlertOperation.m
#import "AlertOperation.h"
#interface AlertOperation()
{
UIAlertView *_alert;
}
#end
#implementation AlertOperation
#synthesize isFinishedAlert = _isFinishedAlert;
- (AlertOperation *)initWithAlert:(UIAlertView *)alert
{
self = [super init];
if (self)
{
_alert = alert;
_alert.delegate = self;
[_alert show];
}
return self;
}
- (void) main
{
_isFinishedAlert = NO;
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!_isFinishedAlert);
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
_isFinishedAlert = YES;
}
- (BOOL) isConcurrent
{
return NO;
}
#end
Here is run code
UIAlertView *u1 = [[UIAlertView alloc] initWithTitle:#""
message:#"Hello i am first alert" delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
UIAlertView *u2 = [[UIAlertView alloc] initWithTitle:#""
message:#"Hello i am second alert" delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
NSOperation *alertOp1 = [[AlertOperation alloc] initWithAlert:u1];
NSOperation *alertOp2 = [[AlertOperation alloc] initWithAlert:u2];
alertsQueue = [[NSOperationQueue alloc] init];
[alertsQueue setMaxConcurrentOperationCount:1];
[alertsQueue addOperation:alertOp1];
[alertsQueue addOperation:alertOp2];
Make this easier on yourself. Create a mutable array. When you have new alerts to show then push them onto the array. Every time an alert finishes (gets its delegate message), then dispatch the next alert onto the main queue:
NSMutableArray *alerts;
... end of Alert Delegate message
if([alert count]) {
UIAlert *alrt = [alerts objectAtIndex:0];
[alerts removeObjectAtIndex:0];
dispatch_async(dispatch_get_main_queue(), ^{ [alrt show]; } );
}
I moved the [_alert show] to -(void)main method and it worked! Thank you, #phix23 for help!

How do I make an alert show how long it took to complete a certain amount of questions in xcode?

I want to show the user how long it took him or her to answer a certain amount of questions (for example 5) as an alert. I believe that I have the correct timer in place although I could be wrong. How would I finish the coding?
- (void)updateCounter:(NSTimer *)theTimer {
static int count = 0;
count += 1;
NSString *s = [[NSString alloc]
initWithFormat:#"%d", count];
self.timer.text = s;
[s release];
}
- (void)generate
{
int a = 1 + arc4random() % 12;
int b = 1 + arc4random() % 12;
int sum = a * b;
label.text = [NSString stringWithFormat: #"%d * %d = ", a, b];
label.tag = sum;
}
- (void)viewDidLoad
{NSLog(#"viewDidLoad");
[super viewDidLoad];
[self generate];
[self.answer becomeFirstResponder];
UIAlertView *alert;
{alert = [[UIAlertView alloc]
initWithTitle:#"Welcome to iCanMultiply!"
message:#"Tap 'Start' to start the game"
delegate: self
cancelButtonTitle:#"Start"
otherButtonTitles: nil];
}
[alert show];
[alert release];
[NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(updateCounter:)
userInfo:nil
repeats:YES];
}
- (IBAction)submit:(id)sender {
int num = [answer.text intValue];
UIAlertView *alert;
if (num == label.tag)
{
// answer was correct
alert = [[UIAlertView alloc]
initWithTitle:#"Correct"
message:#"Bet you can't do that twice!"
delegate:self
cancelButtonTitle:#"Next Question"
otherButtonTitles: nil];
// use the alert tag to mark that answer was correct
alert.tag = 1;
} else
{
// answer is incorrect
alert = [[UIAlertView alloc]
initWithTitle:#"Wrong!"
message:#"Sorry, try again..."
delegate:self
cancelButtonTitle:#"Try Again"
otherButtonTitles: nil];
}
// show and release the alert
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 1)
{
[self generate];
answer.text = #"";
}
}
Store that value and then display it in an alert view.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Title" message#"It took you %# seconds.",time delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
Let me know if the ,time works. I haven't tested this yet, but it should work.

Resources