有没有简单的方法来处理 UIAlertView 结果而无需委托?
Posted
技术标签:
【中文标题】有没有简单的方法来处理 UIAlertView 结果而无需委托?【英文标题】:is there easy way to handle UIAlertView result without delegation? 【发布时间】:2012-03-12 04:49:51 【问题描述】:我有一个函数显示一个带有是/否按钮的 UIAlertView,它只在函数的范围内使用,所以我不想实现一个委托来捕捉用户反馈。
有没有办法知道用户点击了哪些按钮而不实现 UIAlertViewDelegate,例如:
[alert show];
if([alert indexOfClickedButton] == indexOfYes)
....
或动画中的 lambda 表达式
【问题讨论】:
没有委托的 UIALertview 只有一种方法可以创建自定义 UIALertview。 这是一个实现基于块的 UIAlertview(以及其他东西)的站点:blog.mugunthkumar.com/coding/… UIAlertView *aletView = [[UIAlertView alloc] initWithTitle:@"Any Title" message:@"Hiii" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; [警报显示];如果你愿意,不要使用任何委托。 【参考方案1】:没有办法完全避免委托,但您可以按照以下思路创建一个包装器:
@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
];
【讨论】:
我在您执行delegate = nil
的行上收到编译器警告:在此块中强烈捕获委托可能会导致保留周期。这在 ios 5.1 ARC 下。
delegate = nil
是必要的,因为alertView.delegate
是非保留属性,我们需要保留对象“委托”,直到警报视图按钮回调完成。警告(误报)可以在之前使用#pragma clang diagnostic push
和#pragma clang diagnostic ignored "-Warc-retain-cycles"
,在该行之后使用#pragma clang diagnostic pop
来忽略。
太好了,谢谢!您可以在创建警报时传递delegate:nil
。
2015 年更新:UIAlertView
已弃用,其替代品 UIAlertController
允许使用 UIAlertAction
添加操作,它将块作为操作处理程序。【参考方案2】:
我写了一篇关于如何(以及为什么)将块回调添加到警报视图、操作表和动画的博客文章:
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];
【讨论】:
【参考方案3】:这很容易。假设您有一个警报,如下所示:
//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
【讨论】:
但他特意问了如何无需授权... 谢谢!是的,它会为我节省一些代码行,但我仍然需要在函数范围之外编写一些代码,并且可能保存 alertview 的引用,这是我不想要的。我正在寻找基于块的解决方案,如果没有简单的方法可以做到这一点,我认为您的解决方案将是最好的。 很高兴我能帮上忙! @jAckOdE 如果您不想保留警报视图对象的引用,您可以使用标签作为警报视图。例如,警报 = 101;在 - (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 中,您可以检查,如果 alert.tag == 101 ....【参考方案4】:您可以使用自定义视图来执行此操作,该视图可以隐藏和显示以避免 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;
【讨论】:
【参考方案5】:无需派生类。使用 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
【讨论】:
【参考方案6】:谢谢Arkku。这是 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)")
【讨论】:
【参考方案7】: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)
【讨论】:
以上是关于有没有简单的方法来处理 UIAlertView 结果而无需委托?的主要内容,如果未能解决你的问题,请参考以下文章
UIALertView的基本用法与UIAlertViewDelegate对对话框的事件处理方法