¿Hay una manera fácil de manejar el resultado de UIAlertView sin delegación?

Tengo una function que muestra un UIAlertView con botones SÍ / NO, y se usa solo dentro del scope de la function, por lo que no quiero implementar una delegación para captar los comentarios del usuario.

¿Hay alguna forma de saber qué button hicieron clic los usuarios sin implementar UIAlertViewDelegate, algo así como:

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

O expresión lambda como en Animación

No hay forma de evitar la delegación por completo, pero puede crear un contenedor a ese efecto en estas líneas:

 @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 

(Se supone que ARC, si no lo está utilizando, cambie delegate = nil a [delegate release] .)

El uso sería algo así como:

 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 }]; 

He escrito una publicación de blog sobre cómo (y por qué) agregar retrollamadas de bloque para alertar vistas, hojas de acción y animaciones:

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

Si solo quieres una implementación de esto, puedes download los files de fonts de GitHub:

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

Uso:

 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]; 

Es muy fácil. Di que tienes una alerta, algo como esto:

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

Necesitarás agregar este método:

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

Una posible implementación de este método se vería así:

  - (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 } } 

Puede hacer esto usando una vista personalizada que se puede ocultar y mostrar para evitar 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; } 

No es necesario derivar la class. Con Block, es fácil get el índice del button seleccionado por el usuario.

 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 

Gracias Arkku . Aquí está la versión Swift.

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)") } 

UIAlertView está en desuso de iOS 8.0, una mejor solución usará UIAlertController :

 let alert = UIAlertController(title: "message", message: "Title", prefernetworkingStyle: .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)