Block for UIAlertViewDelegate

前端 未结 11 1383
悲哀的现实
悲哀的现实 2020-12-23 12:15

I\'m pretty new to objective C and I\'m just trying to figure out if I can use a block or a selector as the UIAlertViewDelegate argument for UIAlertView - and which is more

相关标签:
11条回答
  • 2020-12-23 12:51

    This is an update to danh's implementation, which is incomplete because it is not possible to add multiple buttons. Passing a va_list to a function is a little tricky :-)

    So you could do this, in order to be able to add multiple buttons to the UIAlertView:

    - (id)initWithTitle:(NSString *)title message:(NSString *)message completion:(void (^)(NSInteger buttonIndex))completion cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... {
    
        self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil ];
    
    
        if(self){
            _completion = completion;
    
            va_list _arguments;
            va_start(_arguments, otherButtonTitles);
    
            for (NSString *key = otherButtonTitles; key != nil; key = (__bridge NSString *)va_arg(_arguments, void *)) {
                    [self addButtonWithTitle:key];
            }
            va_end(_arguments);
    
        }
    
        return self;
    }
    

    Update: There might be a better way of passing the va_list to super. I would like to mention that to me va_lists have something mystic to them :-)

    0 讨论(0)
  • 2020-12-23 12:51

    Awesome idea. I have just completed exactly your idea using Category pattern, no subclass, call directly UIAlertView. Please follow these steps:

    1. Category UIAlertView in .h file

      @interface UIAlertView (AlertWithBlock)
      
         - (void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
         - (void)setDelegateBlock:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
      
         + (id)alertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString   *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles delegate:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegate;
      
      @end
      
    2. In .m file

      @implementation UIAlertView(AlertWithBlock)
      
      static char const *delegateBlockTagKey = "delegateBlockTagKey";
      
      - (void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock
      {
          return objc_getAssociatedObject(self, delegateBlockTagKey);
      }
      
      - (void)setDelegateBlock:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock
      {
          objc_setAssociatedObject(self, delegateBlockTagKey, delegateBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
      }
      
      + (id)alertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles delegate:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegate
      {
          UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
          alert.delegate = alert;
          alert.delegateBlock = [delegate copy];
      
          for (NSString *buttonTitle in otherButtonTitles)
          {
              [alert addButtonWithTitle:buttonTitle];
          }
      
          [alert show];
      
          return alert;
      }
      
      #pragma mark - Delegate
      -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
      {
          if (alertView.delegateBlock)
          {
              alertView.delegateBlock(alertView, buttonIndex);
          }
      }
      
      @end
      
    3. Call like this

      [UIAlertView alertWithTitle:@"Title" message:@"This is a message" cancelButtonTitle:@"Cancel" otherButtonTitles:@[@"Yes",@"No"] delegate:^(UIAlertView *alertView, NSInteger buttonIndex) {
      NSLog(@"Click at button index %ld", buttonIndex);
      }];
      

    Hope it help.

    0 讨论(0)
  • 2020-12-23 12:54

    I have written a simple extension in Swift, hope it helpful

    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)
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-23 12:57

    I had to edit the calling example a bit to stop complier error. Just a small tweak and xcode was happy.

    UIAlertViewBlock *alert = [[UIAlertViewBlock alloc] initWithTitle:@"hi"
                                                              message:@"hi there"
                                                           completion:^(BOOL canceled,NSInteger buttonIndex) {
                                                               NSLog(@"canceled=%d", canceled);
                                                               NSLog(@"pressed=%d", buttonIndex);
                                                           }
                                                   cancelButtonTitle:@"cancel"
                                                    otherButtonTitles:@"ok", nil];
    [alert show];
    
    0 讨论(0)
  • 2020-12-23 12:58

    One must use UIAlertController for that approach as Apple document says

    A UIAlertController object displays an alert message to the user. This class replaces the UIActionSheet and UIAlertView classes for displaying alerts. After configuring the alert controller with the actions and style you want, present it using the presentViewController:animated:completion: method.

    In addition to displaying a message to a user, you can associate actions with your alert controller to give the user a way to respond. For each action you add using the addAction: method, the alert controller configures a button with the action details. When the user taps that action, the alert controller executes the block you provided when creating the action object. Apple Docs.

    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"
    
    
           message:@"This is an alert."
                                       preferredStyle:UIAlertControllerStyleAlert];
    
        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
           handler:^(UIAlertAction * action) {}];
    
        [alert addAction:defaultAction];
        [self presentViewController:alert animated:YES completion:nil];
    
    0 讨论(0)
提交回复
热议问题