Tutorial :Using UIAlertView in a manner similar to Windows' MessageBox()?



Question:

I'm new to the iPhone and I would like to be able to use UIAlertView in a manner similar to the Windows MessageBox() or the MessageDlg() in Delphi.

For example, I have a method that needs to ask the user for confirmation on something, and proceed based on their response.

E.g. (pseudocode):

-(void)doSomething  {    [doStep1];    [doStep2];    var myValue = [getDefaultValue];      if (myValue = nil)    {      if [promptUser(@"No value in setting. Use the default value?")] //UIAlertView here?      {         myValue = @"defaultValue";      }      else        return;  // bug out of the routine 'cause we have no value.    }      [doStep3 withValue:myValue];    }  

Or, put put it another way- is there a way of using UIAlertView to ask the user a question within a routine as a way of controlling the logic flow of that routine?


Solution:1

I have no idea what MessageDlg() is, but you can certainly subclass UIAlertView and handle the dialog response, based on which button is pressed, e.g.:

Set up the UIAlertView subclass header:

//  //  ARReachabilityAlertView.h  //    #import <UIKit/UIKit.h>    @interface ARReachabilityAlertView : UIAlertView <UIAlertViewDelegate> {  }    @end  

Set up the UIAlertView subclass implementation:

//  //  ARReachabilityAlertView.m  //    #import "ARReachabilityAlertView.h"    @implementation ARReachabilityAlertView    - (id)initWithFrame:(CGRect)frame {    if (self = [super initWithFrame:frame]) {      [self setTitle:@"Error"];      [self setMessage:@"This application won't run without a network connection. Do you want to quit?"];      [self addButtonWithTitle:@"Quit"];      [self addButtonWithTitle:@"Continue"];      [self setDelegate:self];    }    return self;  }    - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {    if (buttonIndex == 0)      exit(0); // quit application if "Quit" is pressed; otherwise, do nothing  }    - (void) drawRect:(CGRect)rect {    [super drawRect:rect];  }    - (void) dealloc {    [super dealloc];  }    @end  

Note the alertView:clickedButtonAtIndex: delegate method. This handles the conditionals you use to decide how the application proceeds. You can send an NSNotification from here, or call a method in the application delegate, whatever you want.

In my example, this UIAlertView is instantiated if there is no network connection, and the application is closed if the user clicks "Quit" in the alert view. Otherwise, if the user clicks "Continue" the application keeps running as usual.

Note that the implementation of the subclass requires the drawRect: method be called. I'm not sure if this is a bug or not, since I'd expect the drawRect: method to be called in the super-class; I filed a bug report with Apple on this one, but I haven't heard anything. Comment it out if you want to see what the effect will be â€" it's kind of interesting.


Solution:2

There's no reason to subclass UIAlertView at all. That's what delegates are for. All you need is a class (such as your view controller) supporting the UIAlertViewDelegate protocol, and set the UIAlertView's delegate property to that class. You then implement the alertView:clickedButtonAtIndex: method in this class, and the alertViewCancel: method if you want to specifically handle cancellations differently.

You can read more about it in the UIAlertView documentation and in the UIAlertViewDelegate documentation.


Solution:3

I believe you're looking to use UIAlertView as a modal alert box (in the sense that you'd like your code to stop running until the user makes a selection). There's no easy way to do this, and it's really recommended that you NOT code for the iPhone in this manner. I think Alex's explanation is a good solution.


Solution:4

To do this, what you can do is to run the mainloop manually. I have not managed to stop the mainloop directly, so I instead run the mainloop for 0.5 seconds and wait until the user responds.

I ran into this question while researching the problem for a C#/MonoTouch user on the iPhone. The sample below is written for MonoTouch/C# but should be trivial to translate to Objective-C

The following function shows how you could implement a modal query with the above approach:

int WaitForClick ()  {      int clicked = -1;      var x = new UIAlertView ("Title", "Message",  null, "Cancel", "OK", "Perhaps");      x.Show ();      bool done = false;      x.Clicked += (sender, buttonArgs) => {          Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);      clicked = buttonArgs.ButtonIndex;      };          while (clicked == -1){          NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));          Console.WriteLine ("Waiting for another 0.5 seconds");      }        Console.WriteLine ("The user clicked {0}", clicked);      return clicked;  }  


Solution:5

Just a quick tip: if you want a class to be a delegate for more than one UIAlertView, just use tag property to tell who is who:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Clear all" message:@"Are you sure you want to erase everything?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];  alert.tag = ALERT_DELETE_TAG;  [alert autorelease];  [alert show];  

Delegate methods are called with UIAlertView as first argument, and you can check who's the originator there.


Solution:6

Thanks to @miguel.de.icaza I found my solution like below (part of the code):

@interface MyClass: NSObject <UIAlertViewDelegate>  {     int confirmed;  }  - (BOOL) removeObjectAtIndex:(NSUInteger)index;  @end    @implementation    - (BOOL) removeObjectAtIndex:(NSUInteger)index  {         // delete confirmation alert      confirmed = -1;        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Delete confirmation" message:@"Are you sure to delete object" delegate:self cancelButtonTitle:@"Yes" otherButtonTitles: @"No", nil];      alert.tag = 2;      [alert show];      [alert release];        // wait for confirm (0 or 1)      while (confirmed == -1) {          // this is what you need!!!          [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];      }        if (confirmed) {          [myObjects removeObjectAtIndex:index];          return YES;      }      else          return NO;  }    - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex  {      switch (alertView.tag) {          case 1:              // ...              break;          case 2:              if (buttonIndex == 0) // delete confirmed                  confirmed = 1;              else                  // dismiss                  confirmed = 0;              break;          default:              break;      }  }    @end  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »