Есть ли простой способ обработки результатов UIAlertView без делегирования? - PullRequest
8 голосов
/ 12 марта 2012

У меня есть функция, которая отображает UIAlertView с кнопками YES / NO, и она используется только внутри области действия функции, поэтому я не хочу реализовывать делегирование для получения отзывов пользователей.

Есть ли способ узнать, на какую кнопку нажимали пользователи, без реализации UIAlertViewDelegate, что-то вроде:

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

Или лямбда-выражение, как в анимации

Ответы [ 7 ]

23 голосов
/ 12 марта 2012

Невозможно полностью избежать делегирования, но вы можете создать оболочку на этот счет по следующим направлениям:

@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, если вы не используете его, измените delegate = nil на[delegate release].)

Использование будет примерно таким:

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
}];
3 голосов
/ 26 февраля 2014

Я написал сообщение в блоге о том, как (и почему) добавить обратные вызовы блоков для просмотра предупреждений, листов действий и анимации:

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

Если вы просто хотите работающую реализациюиз этого вы можете скачать исходные файлы с GitHub:

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

Использование:

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];
1 голос
/ 12 марта 2012

Это очень просто. Скажем, у вас есть предупреждение, что-то вроде этого:

//Alert
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

Возможная реализация этого метода будет выглядеть следующим образом:

 - (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
    }
}
0 голосов
/ 28 марта 2016

UIAlertView устарела с iOS 8.0, лучшее решение будет использовать 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)
0 голосов
/ 19 марта 2015

Спасибо Арку . Вот версия 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)")
}
0 голосов
/ 22 февраля 2014

Нет необходимости выводить класс. С помощью блока легко получить выбранный пользователем индекс кнопки.

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
0 голосов
/ 12 марта 2012

Вы можете сделать это, используя пользовательский вид, который можно скрыть и показать, чтобы избежать 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;

 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...