jAckOdE
jAckOdE

Reputation: 2510

is there easy way to handle UIAlertView result without delegation?

I have a function that shows a UIAlertView with YES/NO buttons, and it is used only inside the function's scope so I dont want to implement a delegation to catch the user feedback.

Is there any way to know what button users clicked without implement UIAlertViewDelegate, something like:

[alert show];
if([alert indexOfClickedButton] == indexOfYes)
{
....
}

Or lambda expression as in Animation

Upvotes: 8

Views: 17863

Answers (7)

Idan Yehuda
Idan Yehuda

Reputation: 560

UIAlertView is deprecated from iOS 8.0, a better solution will be using UIAlertController:

let alert = UIAlertController(title: "message", message: "Title", preferredStyle: .Alert)

alert.addAction(UIAlertAction(title: "YES", style: .Default, handler: { (action) -> Void in
    // Action for YES
}))
alert.addAction(UIAlertAction(title: "NO", style: .Default, handler: { (action) -> Void in
    // Action for NO
}))

self.view.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)

Upvotes: 0

Evgenii
Evgenii

Reputation: 37339

Thanks Arkku. Here is the Swift version.

https://github.com/exchangegroup/alert-view-with-callback-swift

let alertView = UIAlertView(...)

AlertViewWithCallback().show(alertView) { alertView, buttonIndex in
  println("You closed alert by tapping button #\(buttonIndex)")
}

Upvotes: 0

Arkku
Arkku

Reputation: 42149

There is no way to avoid delegation completely, but you could create a wrapper to that effect along these lines:

@interface MyAlertViewDelegate : NSObject<UIAlertViewDelegate>

typedef void (^AlertViewCompletionBlock)(NSInteger buttonIndex);
@property (strong,nonatomic) AlertViewCompletionBlock callback;

+ (void)showAlertView:(UIAlertView *)alertView withCallback:(AlertViewCompletionBlock)callback;

@end


@implementation MyAlertViewDelegate
@synthesize callback;

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    callback(buttonIndex);
}

+ (void)showAlertView:(UIAlertView *)alertView
         withCallback:(AlertViewCompletionBlock)callback {
    __block MyAlertViewDelegate *delegate = [[MyAlertViewDelegate alloc] init];
    alertView.delegate = delegate;
    delegate.callback = ^(NSInteger buttonIndex) {
        callback(buttonIndex);
        alertView.delegate = nil;
        delegate = nil;
    };
    [alertView show];
}

@end

(ARC is assumed, if you are not using it change delegate = nil to [delegate release].)

Usage would be something like:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil];
[MyAlertViewDelegate showAlertView:alert withCallback:^(NSInteger buttonIndex) {
    // code to take action depending on the value of buttonIndex
}];

Upvotes: 23

Desmond
Desmond

Reputation: 696

I have written a blog post about how to (and why) add block callbacks to alert views, action sheets and animations:

http://blog.innovattic.com/uikitblocks/

If you just want a working implementation of this you can download the sources files from GitHub:

https://github.com/Innovattic/UIKit-Blocks

Usage:

UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"My easy alert"  
                                                message:@"Would you like to perform some kind of action?"
                                      cancelButtonTitle:@"No"
                                      otherButtonTitles:@"Yes", nil];
[alert setHandler:^(UIAlertView* alert, NSInteger buttonIndex) {
    NSLog(@"Perform some kind of action");
} forButtonAtIndex:[alert firstOtherButtonIndex]];
[alert show];

Upvotes: 3

bademi
bademi

Reputation: 421

No need to derive the class. With Block, it is easy to get user selected button index.

typedef void(^AlertViewCallBackBlock)(NSInteger selectedIndex);

@interface ABC ()
    @property (nonatomic, copy) AlertViewCallBackBlock alertViewBlock;
@end

@implementation

- (void)showAlert {
    self.alertViewBlock = ^(NSInteger selectedIndex) {
        if (selectedIndex == 1) {

        }
    };
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil];
    [alert show];
}

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    self.alertViewBlock(buttonIndex);
}
@end

Upvotes: 0

Sanket Pandya
Sanket Pandya

Reputation: 1095

You can do this using custom view which can be hidden and shown to avoid ActionSheets

UIView *AlertVw=[UIView alloc]initWithFrame:CGRect(x,y,w,h)]];

UIButton *SaveButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]];
[CustomButton setTitle:@"Ok" forState:UIControlStateNormal];
[SaveButton addTarget:self action:@selector(SaveClicked)            forControlEvents:UIControlEventTouchUpInside];

UIButton *CancelButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]];
[CustomButton setTitle:@"Cancel" forState:UIControlStateNormal];
[CancelButton addTarget:self action:@selector(CancelClicked)            forControlEvents:UIControlEventTouchUpInside];

[AlertVw addSubview:SaveButton];
[AlertVw addSubview:CancelButton];

[self.view addSubview:AlertVw];

-(void)SaveButton
 {
   //Code to apply on Save clicked
  [AlertVw removeFromSuperView];  //Also you can use AlertView.hidden=YES;

 }
-(void)CancelButton
 {
   //Code to apply on cancel clicked
  [AlertVw removeFromSuperView];  //Also you can use AlertView.hidden=YES;

 }

Upvotes: 0

Jtaylorapps
Jtaylorapps

Reputation: 5780

It's very easy. Say you have an alert, something like this:

//Alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil];
[alert show];

You're going to need to add this method:

 - (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

A possible implementation of this method would look like this:

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

//Checks For Approval
    if (buttonIndex == 1) {
        //do something because they selected button one, yes
    } else {
        //do nothing because they selected no
    }
}

Upvotes: 1

Related Questions