xcode 有没有简单的方法可以在没有委托的情况下处理 UIAlertView 结果?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9661900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 23:36:25  来源:igfitidea点击:

is there easy way to handle UIAlertView result without delegation?

iphoneiosxcodecocoa-touch

提问by HymanOdE

I have a function that shows a UIAlertView with YES/NO buttons, and it is used only inside the function's scope so I dont want to implement a delegation to catch the user feedback.

我有一个显示带有 YES/NO 按钮的 UIAlertView 的函数,它只在函数的范围内使用,所以我不想实现一个委托来捕捉用户反馈。

Is there any way to know what button users clicked without implement UIAlertViewDelegate, something like:

有没有办法知道用户在不实现 UIAlertViewDelegate 的情况下单击了什么按钮,例如:

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

Or lambda expression as in Animation

或动画中的 lambda 表达式

回答by Arkku

There is no way to avoid delegation completely, but you could create a wrapper to that effect along these lines:

没有办法完全避免委托,但您可以按照以下方式创建一个包装器来实现该效果:

@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 is assumed, if you are not using it change delegate = nilto [delegate release].)

(假设为 ARC,如果您不使用它,请更改delegate = nil[delegate release].)

Usage would be something like:

用法类似于:

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

回答by Desmond

I have written a blog post about how to (and why) add block callbacks to alert views, action sheets and animations:

我写了一篇关于如何(以及为什么)向警报视图、动作表和动画添加块回调的博客文章:

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

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

If you just want a working implementation of this you can download the sources files from GitHub:

如果你只是想要一个有效的实现,你可以从 GitHub 下载源文件:

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

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

Usage:

用法:

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

回答by JTApps

It's very easy. Say you have an alert, something like this:

这很容易。假设您有一个警报,如下所示:

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

You're going to need to add this method:

您将需要添加此方法:

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

A possible implementation of this method would look like this:

此方法的可能实现如下所示:

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

回答by Sanket Pandya

You can do this using custom view which can be hidden and shown to avoid ActionSheets

您可以使用自定义视图来执行此操作,该视图可以隐藏和显示以避免 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;

 }

回答by bademi

No need to derive the class. With Block, it is easy to get user selected button index.

不需要派生类。使用 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

回答by Evgenii

Thanks Arkku. Here is the Swift version.

谢谢阿库。这是 Swift 版本。

https://github.com/exchangegroup/alert-view-with-callback-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)")
}

回答by idanuda

UIAlertViewis deprecated from iOS 8.0, a better solution will be using UIAlertController:

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)