2012-03-12 6 views
8

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

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

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

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

+1

UIAlertView без делегации есть только один способ, что и создать пользовательский UIAlertView. – ios

+2

Вот сайт, который реализует блочный UIAlertview (наряду с другими вещами): http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ – lnafziger

+0

UIAlertView * aletView = [[UIAlertView alloc] initWithTitle: @ Сообщение «Any Title»: @ «Hiii» делегат: self cancelButtonTitle: @ «Отменить» otherButtonTitles: nil, nil]; [alert show]; не используйте делегатов, если хотите. –

ответ

23

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

@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].)

Usage будет что-то вроде:

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

спасибо, ваше решение работает. – jAckOdE

+1

Я получаю предупреждение о компиляторе в строке, где вы выполняете 'delegate = nil', говоря:« Захват делегата в этом блоке, скорее всего, приведет к циклу сохранения. Это под iOS 5.1 ARC. –

+1

'delegate = nil' необходимо, потому что' alertView.delegate' является не сохраняющим свойством, и нам нужно сохранить объект «делегировать» до тех пор, пока не появится обратный вызов кнопки предупреждения. Предупреждение (ложноположительное) можно игнорировать с помощью «#pragma clang diagnostic push» и «#pragma clang diagnostic ignored» -Warc-keep-cycles »' before, и '#pragma clang diagnostic pop' после этой строки. – AndiDog

1

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

//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 
    } 
} 
+13

Но он специально спросил, как это сделать: без делегации ... – Arkku

+0

Не читал очень внимательно. Если это помогает, это помогает – JTApps

+0

Спасибо! И да, это сэкономит мне некоторую строку кодов, но мне все равно придется писать код за пределами области действия и, возможно, сохранить ссылку на alertview, чего я не хочу. Я ищу блочное решение, и если нет простого способа сделать это, я думаю, что ваше решение будет лучшим. – jAckOdE

0

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

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; 

} 
0

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

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 
3

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

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

нашли ответ давным-давно, но все же, это хорошие работы – jAckOdE

0

UIAlertView устарела с прошивкой 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)