【问题标题】:Custom UIAlertView with block callback带有块回调的自定义 UIAlertView
【发布时间】:2012-12-13 08:34:52
【问题描述】:

MyAlertView(UIAlertView 的子类)有这个方法:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (self.clickedButtonAtIndexBlock != NULL)
        self.clickedButtonAtIndexBlock(buttonIndex);
}

我的问题是如何在创建警报视图时定义回调?显然这是错误的:

alert.clickedButtonAtIndexBlock = ^{
    NSLog(@"clicked: %d", buttonIndex);
}

【问题讨论】:

    标签: ios block uialertview objective-c-blocks


    【解决方案1】:

    尝试做这样的事情(我还没有测试过):

    .h
    typedef void (^MyClickedIndexBlock)(NSInteger index);
    
    @interface YouInterface : YourSuperclass
    @property (nonatomic, strong) MyClickedIndexBlock clickedIndexBlock;
    @end
    
    .m
    //where you have to call the block
    if (self.clickedIndexBlock != nil)
        self.clickedIndexBlock(buttonIndex);
    
    // where you want to receive the callback
    alert.clickedIndexBlock = ^(NSInteger index){
        NSLog(@"%d", index);
    };
    

    【讨论】:

      【解决方案2】:

      试试这个

      假设您创建了一个名为 MyCustomAlert 的类,并将其声明为该变量。

      MyCustomAlert *myCustomAlert = [[MyCustomAlent alloc] init];
      

      你可以把它放在你的头文件中。

      - (void)setCompletion:(void (^)(int selectedButtonIndex))completion;
      

      你会把它放在你的实现文件中

      typedef void (^IntBlock)(int intBlock);
      IntBlock _completion;
      
      - (void)setCompletion:(void (^)(int selectedButtonIndex))completion{
          _completion = completion;
      }
      

      现在在您声明“myCustomAlert”的项目中。如果你输入

      [myCustomAlert setCompletion: // And select the autocomplete item
      

      你最终会得到这个

      [myCustomAlert setCompletion:<#^(int intBlock)completion#>]
      

      值 将显示为像这样的气泡。

      当你在值上按回车时,它会填写块供你使用。

      [myCustomAlert setCompletion:^(int selectedButtonIndex) {
      
      }
      

      当您想在自定义类中触发 _completion 块时,您可以在代码中的某处调用它,如下所示。

      - (void) callCompletionWithButtonIndex:(int) index{
          if (_completion != nil) _completion(index);
      }
      

      希望能解决这个问题。

      【讨论】:

      • 在这个答案中,您没有显示您所指的头文件/实现文件。您还介绍了自定义警报概念,但没有解释它如何适合解决方案。这迫使读者猜测你的意图(这总是不好的)。通过解决这些错失的机会,可以改善答案。
      • 我指的头文件和实现文件是你的,不是我的。因此,我无法为您提供一个,因为这意味着要放入您的代码中。但是您是对的,我没有提供 _completion 调用。我已经添加了。
      • 当你提到一个头文件和实现文件时,它是如何关联的?它是视图控制器还是自定义警报的子类?抱歉,如果我之前的要求不清楚。我可以简单地假设后者,但特异性总是更好。
      • 头文件和实现文件是你想要使用这个函数指针的类的.h和.m文件。你可以继承 UIAlertView,你可以创建一个 AlertManager,你可以把它放在你的 ViewController 上,这真的取决于你想做什么。该信息仅显示如何实现回调函数,以便您可以创建回调,使用它以及如何允许编辑器为您提供块本身:)
      【解决方案3】:

      我编写了一个简单的类 LMSVBlocks 来轻松显示警报并在 1 行中获取块回调。希望您会发现它对此有用

      https://github.com/sourabhverma/LMSVBlocks

      概念:要使 UIAlertView 块兼容,您需要另一个类(例如 LMSVBlockAlert)来处理委托方法,并且当 UIAlertView 委托将给出回调时,LMSVBlockAlert 类可以在块中发送回调。

      代码: (LMSVBlockAlert.m)

      在一个数组中维护所有 LMSVBlockAlert 的实例,以便它们具有强引用

      static NSMutableArray *_LMSVblockHandlersArray = nil;
      

      将块处理程序保留在 LMSVBlockAlert 中

      @interface LMSVBlockAlert() <UIAlertViewDelegate>
      @property (nonatomic, copy) void (^cancelCompletionBlock)();
      @property (nonatomic, copy) void (^confirmCompletionBlock)();
      @end
      

      当触发新警报时,创建具有 UIAlertView 和委托回调的 LMSVBlockAlert 新实例

      +(LMSVBlockAlert*)newInstance{
          LMSVBlockAlert *newIns = [[LMSVBlockAlert alloc] init];
          [LMSVBlockAlert updateHandlerArrayWith:newIns];
          return newIns;
      }
      

      当警报委托在 LMSVBlockAlert 中触发时,发送回调以阻止并从内存中清除它

      - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
      
          switch (buttonIndex) {
              case 0://Cancel
              {
                  if(_cancelCompletionBlock){
                      _cancelCompletionBlock();
                  }
              }
                  break;
              case 1://OK
              {
                  if(_confirmCompletionBlock){
                      _confirmCompletionBlock(alertView);
                  }
              }
                  break;
              default:
                  break;
          }
          [_LMSVblockHandlersArray removeObject:self];
      }
      

      现在你可以有两个简单的方法来给你 UIAlertView 回调

      +(UIAlertView*)promptAlertTwoBtn:(NSString*)msg title:(NSString*)title onCancel:(void (^)())onCancel onConfirm:(void (^)())onConfirm{
      
          return [[LMSVBlockAlert newInstance] showAlertMainWithTitle:title msg:msg onCancel:^{
              onCancel();
          } onConfirm:^(UIAlertView *alertView) {
              onConfirm();
          }];
      }
      
      -(UIAlertView*)showAlertMainWithTitle:(NSString*)title msg:(NSString*)msg onCancel:(void (^)())onCancel onConfirm:(void (^)(UIAlertView*))onConfirm{
      
          UIAlertView *newAlert = nil;
      
      
          newAlert = [[UIAlertView alloc]
                          initWithTitle:title
                          message:msg
                          delegate:self
                          @"Cancel"
                          otherButtonTitles:@"Confirm", nil];
      
      
          [newAlert show];
      
          self.cancelCompletionBlock = onCancel;
          self.confirmCompletionBlock = onConfirm;
      
          return newAlert;
      }
      

      终于 希望你觉得它有用..

      【讨论】:

        【解决方案4】:

        您可以简单地使用来自 github 的这些类别类。

        Alert_ActionSheetWithBlocks

        这为 AlertView 和操作表提供了 Dismiss 块。

        例如。

        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"AlertView+Block" message:@"WithBlocks" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"newAlertViewWithTextFields",@"newAlertViewWithSingleTextField", nil];
        [alert showWithFinishBlock:^(UIAlertView *alertView, NSInteger buttonIndex) 
        { if (buttonIndex == 0) { } else if (buttonIndex == 1) { } }];
        

        除此之外,它还提供文本字段的方法..

        -(void) showWithFinishBlock:(FinishBlock_)block_; //-- AlertView with TextField [simple or secure]
        
        -(void) showWithTextFieldBlock:(TextFieldBlock_)block_ secure:(BOOL)isSecure; //-- AlertView with two textfields username & password
        

        您可以查看与它捆绑的示例。 希望对你有帮助。

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

            我用 Swift 写了一个简单的扩展,希望对你有帮助

            import UIKit
            
            extension UIAlertView {
            
                func show(completion: (alertView: UIAlertView, buttonIndex: Int) -> Void){
                    self.delegate = AlertViewDelegate(completion: completion)
                    self.show()
                }
            
                class func showInput(title: String?, message: String?, cancellable: Bool, completion: (text: String?) -> Void){
            
                    var strOK = NSLocalizedString("OK",comment: "OK")
                    var strCancel = NSLocalizedString("Cancel",comment: "Cancel")
                    var alert = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: cancellable ? strCancel : strOK)
                    alert.alertViewStyle = UIAlertViewStyle.PlainTextInput
                    if(cancellable) {
                        alert.addButtonWithTitle(strOK)
                    }
                    alert.show { (alertView, buttonIndex) -> Void in
                        if(cancellable && alertView.cancelButtonIndex == buttonIndex) {
                            completion(text: nil)
                            return
                        }
                        completion(text: alertView.textFieldAtIndex(0)?.text)
                    }
                }
            
                private class AlertViewDelegate : NSObject, UIAlertViewDelegate {
                    var completion :  (alertView: UIAlertView, buttonIndex: Int) -> Void
                    var retainedSelf : NSObject?
                    init(completion: (UIAlertView, Int) -> Void ) {
                        self.completion = completion
                        super.init()
            
                        self.retainedSelf = self
                    }
            
                    func alertView(alertView: UIAlertView, didDismissWithButtonIndex buttonIndex: Int) {
                        var retain = self
                        retain.retainedSelf = nil
                        retain.completion(alertView: alertView, buttonIndex: buttonIndex)
                    }
                }
            }
            

            【讨论】:

              【解决方案7】:

              检查这个OpinionzAlertView 我在几个项目中使用过它,对我很有用。这是示例:

              OpinionzAlertView *alert = [[OpinionzAlertView alloc] initWithTitle:@"title"
                                                                          message:@"message"
                                                                cancelButtonTitle:@"No, thanks"
                                                                otherButtonTitles:@[@"Done"]
                                                          usingBlockWhenTapButton:^(OpinionzAlertView *alertView, NSInteger buttonIndex) {
              
                                                              NSLog(@"buttonIndex: %li", (long)buttonIndex);
                                                              NSLog(@"buttonTitle: %@", [alertView buttonTitleAtIndex:buttonIndex]);
                                                          }];
              [alert show];
              

              希望对你有帮助。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-09-24
                • 2010-10-07
                • 2011-10-14
                • 2011-05-10
                • 1970-01-01
                相关资源
                最近更新 更多