开发者

How to write event handlers for buttons in UIAlertView?

开发者 https://www.devze.com 2023-04-04 23:07 出处:网络
Say I have a alert view开发者_StackOverflow社区 like follows in obj c UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@\"title\" message:@\"szMsg\" delegate:nil cancelButtonTitle:@\"Ok\" other

Say I have a alert view开发者_StackOverflow社区 like follows in obj c

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"szMsg" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:@"download"];
        [alert show];
        [alert release];

Now we have 2 buttons on the alert view (Ok & Download), how to write an event handler for the Download one?


First you will need to add the UIAlertViewDelegate to your header file like below:

Header file (.h)

@interface YourViewController : UIViewController<UIAlertViewDelegate> 

Implementation File (.m)

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"szMsg" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:@"download"];
        [alert show];
        [alert release];

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0)
    {
        //Code for OK button
    }
    if (buttonIndex == 1)
    {
        //Code for download button
    }
}


Now that most iOS devices have firmare versions with blocks support it’s an anachronism to use the clumsy callback API to handle button presses. Blocks are the way to go, see for example the Lambda Alert classes on GitHub:

CCAlertView *alert = [[CCAlertView alloc]
    initWithTitle:@"Test Alert"
    message:@"See if the thing works."];
[alert addButtonWithTitle:@"Foo" block:^{ NSLog(@"Foo"); }];
[alert addButtonWithTitle:@"Bar" block:^{ NSLog(@"Bar"); }];
[alert addButtonWithTitle:@"Cancel" block:NULL];
[alert show];


Declare your UIAlertViews as known.

UIAlertView *alertLogout=[[UIAlertView alloc]initWithTitle:@"Title" message:@"Stop Application?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil]; 

[alertLogout show]; 

[alertLogout release];

set delegate to self and implement this method.

-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(actionSheet== alertLogout) {//alertLogout
        if (buttonIndex == 0){

        }else if(buttonIndex==1){

        }
    }else if (actionSheet==alertComment) {//alertComment
        if (buttonIndex==0) {

        }
    }
}


Stack's and Guillermo Ortega's answer is probably what you would use with a couple of UIAlertView but not for ten. I use to use BlocksKit which is kind of the same as Lambda stuff which is what soul suggested. That is a good option too, although if you have too many nested blocks you will start seeing the demerits of it (Aside from the fact you will be relying in another library).

The usual way of handling several stuff would be to have a handler object. ( @interface MyAlertViewDelegate : NSObject <UIAlertViewDelegate> @end) make that object the delegate of the alert view and make sure the object is alive at least until the alert view is dismissed. This will certainly work, but could be too much work...

What follows is what I came up with; IMO it is simpler and there is no need of any thirdParty library, or an ivar per UIAlertView. Just one extra object (@property (nonatomic, strong) NSArray *modalActions) to store the actions the current UIAlertView will cause to perform

Showing an UIAlertView and reacting accordingly

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle
                                                    message:@"Blah blah"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:b1, b2, b3, nil];
// Add one selector/action per button at the proper index
self.modalActions = @[
                   [NSNull null], // Because indexes of UIAlertView buttons start at 1
                   NSStringFromSelector(@selector(actionForAlertViewButton1)),
                   NSStringFromSelector(@selector(actionForAlertViewButton2)),
                   NSStringFromSelector(@selector(actionForAlertViewButton3))];
[alertView show];

The delegate method:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (alertView.cancelButtonIndex != buttonIndex) {
        [self performModalActionAtIndex:buttonIndex];
    }
}

The part that actually performs the action:

- (void)performModalActionAtIndex:(NSInteger)index
{
    if (-1 < index && index < self.modalActions.count &&
        [self.modalActions[index] isKindOfClass:[NSString class]]) {
        SEL action = NSSelectorFromString(self.modalActions[index]);
        NSLog(@"action: %@", self.modalActions[index]);
        if ([self respondsToSelector:action]) {
// There is a situation with performSelector: in ARC.
// http://stackoverflow.com/questions/7017281/
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self performSelector:action];
#pragma clang diagnostic pop
    }
    self.modalActions = nil;
}

Reusable for UIActionSheets too

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title
                                                         delegate:self
                                                cancelButtonTitle:cancelButton  
                                           destructiveButtonTitle:nil 
                                                otherButtonTitles:button1, button2, button3, nil];
// Similarly, add one action per button at the proper index
self.modalActions = @[
                    NSStringFromSelector(@selector(actionForActionSheetButton1)),
                    NSStringFromSelector(@selector(actionForActionSheetButton2)),
                    NSStringFromSelector(@selector(actionForActionSheetButton3))];

The delegate method:

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (actionSheet.cancelButtonIndex != buttonIndex) {
        [self performModalActionAtIndex:buttonIndex];
    }
}

Why this works:

This works because of two reasons:

First, I never present two UIAlertView that have a delegate at the same time. (IMO you should't, it doesn't look good). Second, because in my case (as 90% of the cases) the target of the actions is always the same object (in this case: self). Even if you don't meet above conditions you can even use this approach with some modifications:

  • If you show two or more UIAlerViews or UIActionSheets at the same time (possible in the iPad) Use a dictionary with to store one array of actions associated with a certain UIAlertView/UIActionSheet.

  • If the target of the actions is not self, they you need to store pairs (target and the action) in the array. (Something to simulate UIButtons addTarget:action:...).

In either case, for storing the target and/or UIActionSheet/UIAlertView [NSValue valueWithNonretainedObject:] should become handy :)


First of all you declare UIAlertViewDelegate in .h file after put below code in .m file

- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex 
{

   if (buttonIndex == 1) 
    {
         //put button action which you want.
    }
}


Implement the UIAlertViewDelegate and make use of the delegate method

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
  if(buttonIndex == 0) {
    // Do something
  }
  else {
   // Do something
  }
}


UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"Data Saved" message:@"Choose more photos" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:Nil];
        [alertView show];
        [alertView release];


-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if(buttonIndex==0)
    {
        [self dismissModalViewControllerAnimated:YES];
    }
}


in swift: we can use this little block of code

    let alert = UIAlertController(title: "Alert", message: "This is an alert message", preferredStyle: UIAlertControllerStyle.Alert)

    let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {(action:UIAlertAction) in print("This is in alert block")
    })

    alert.addAction(action)
    self.presentViewController(alert, animated: true, completion: nil)
0

精彩评论

暂无评论...
验证码 换一张
取 消