2012-03-12 51 views
8

我有一个函数,显示一个UIAlertView与YES/NO按钮,它只用于函数的范围内,所以我不想实现一个委托来捕捉用户反馈。有没有委托处理UIAlertView结果的简单方法?

有没有办法知道哪个按钮用户点击不落实UIAlertViewDelegate,是这样的:

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

或lambda表达式,如动画

+1

UIAlertView中没有代表团只有一个,ü创建一个自定义UIAlertView中的方式。 – ios 2012-03-12 05:03:46

+2

这里是一个实现基于块的UIAlertview的网站(以及其他内容):http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ – lnafziger 2012-03-12 05:18:13

+0

UIAlertView * aletView = [[UIAlertView alloc] initWithTitle:@“Any Title”message:@“Hiii”delegate:self cancelButtonTitle:@“Cancel”otherButtonTitles:nil,nil]; [alert show];如果需要, 不使用任何委托。 – 2012-03-12 09:46:51

回答

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]

用法是这样的:

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 2012-03-13 01:27:41

+1

我在执行'delegate = nil'的行上收到编译器警告:在此块中强烈地捕获委托很可能导致保留周期。这在iOS 5.1 ARC下。 – 2012-05-20 13:25:42

+1

'delegate = nil'是必须的,因为'alertView.delegate'是一个非保留属性,我们需要保持对象为“委托”,直到警报视图为按钮回调完成。这个警告(误报)可以用'#pragma clang diagnostic push'和'#pragma clang diagnostic ignored'-Warc-retain-cycles''忽略,并在该行后面加上'#pragma clang diagnostic pop'。 – AndiDog 2013-09-23 11:24:51

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

但他特意问了怎么做_overout delegation_ ... – Arkku 2012-03-12 04:58:30

+0

没有仔细阅读。如果它有帮助 – JTApps 2012-03-12 04:59:35

+0

谢谢!是的,它会为我节省一些代码行,但我仍然需要在函数范围之外编写一些代码,并且可能会保存alertview的引用,这正是我不想要的。我正在寻找一个基于块的解决方案,如果没有简单的方法来做到这一点,我认为你的解决方案将是最好的。 – jAckOdE 2012-03-12 05:31:27

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

无需派生类。使用Block,可以很容易地获得用户选择的按钮索引。

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 2014-02-27 02:59:52

0

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) 
相关问题