2012-04-10 57 views
25

我很新的目標C和我只是想弄清楚,如果我可以使用塊或選擇器作爲UIAlertViewDelegate UIAlertView參數 - 哪個更合適?Block for UIAlertViewDelegate

我試過以下,但它只是不工作,所以我不知道如果我在正確的軌道上?

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Checked In" 
    message:responseString 
    delegate:^(UIAlertView * alertView, NSInteger buttonIndex) 
                { 
                 NSLog(@"Done!"); 
                } 
    cancelButtonTitle:@"OK" 
    otherButtonTitles: nil]; 

謝謝!

+0

蘋果不提供,但它是一個好主意。做到這一點的方法是一個子類。我會盡快發佈併發布。 – danh 2012-04-10 02:32:43

+0

danh的答案有效,但不支持多個按鈕。請參閱下面的答案。 – Besi 2012-08-25 16:44:08

回答

28

好主意。這裏是。就像警報視圖一樣,除了添加一個在警報解除時調用的block屬性。 (編輯 - 我已經簡化,因爲原來的答案該代碼這是我現在使用的項目。)

// AlertView.h 
// 

#import <UIKit/UIKit.h> 

@interface AlertView : UIAlertView 

@property (copy, nonatomic) void (^completion)(BOOL, NSInteger); 

- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles; 

@end 

// 
// AlertView.m 

#import "AlertView.h" 

@interface AlertView() <UIAlertViewDelegate> 

@end 

@implementation AlertView 

- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles { 

    self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil]; 

    if (self) { 
     for (NSString *buttonTitle in otherButtonTitles) { 
      [self addButtonWithTitle:buttonTitle]; 
     } 
    } 
    return self; 
} 

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { 

    if (self.completion) { 
     self.completion(buttonIndex==self.cancelButtonIndex, buttonIndex); 
     self.completion = nil; 
    } 
} 

@end 

您可以擴展這個想法提供其他委託方法塊,但didDismiss是最常見的。

這樣稱呼它:

AlertView *alert = [[AlertView alloc] initWithTitle:@"Really Delete" message:@"Do you really want to delete everything?" cancelButtonTitle:@"Nevermind" otherButtonTitles:@[@"Yes"]]; 

alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) { 
    if (!cancelled) { 
     [self deleteEverything]; 
    } 
}; 
[alert show]; 
+2

下面是一個(完整)danh的想法實現:http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ – thelaws 2012-04-10 02:56:45

+0

您是否嘗試添加多個按鈕? ':-)'見下面的答案。 – Besi 2012-08-25 16:43:20

+1

謝謝@Besi。更新了答案,以正確處理var args來合併代碼。 – danh 2012-08-25 17:05:09

1

這是對danh實現的更新,由於無法添加多個按鈕,因此這是不完整的。路過的va_list的功能是有點棘手:-)

所以,你可以做到這一點,爲了能夠將多個按鈕添加到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; 
} 

更新:有可能將va_list傳遞給super的更好方法。我想提一下,對我來說va_list s有一些神祕的東西給他們:-)

+2

這很好。感謝va arg提示。我會編輯我的答案,以防這一錯過。 – danh 2012-08-25 16:59:23

-2

我不得不編輯調用示例一點,以停止編譯器錯誤。只是一個小小的調整和Xcode很高興。

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

只需使用REKit。它與BlocksKit類似,但功能更強大。

1

真棒想法。我剛剛完成你的想法使用分類模式,沒有子類,直接調用UIAlertView。請按照下列步驟操作:

  1. 類別UIAlertView in。.h文件

    @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. 在.m文件

    @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. 這樣調用

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

希望它能幫助。

+0

不錯!別忘了#import Fracdroid 2015-09-11 19:39:50

1

我已經寫在斯威夫特的簡單延伸,希望它有幫助

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) 
     } 
    } 
} 
2

一個蘋果文件說

一個UIAlertController對象顯示一條警告消息,用戶必須使用UIAlertController於這個方法。這個 類代替了顯示警報的 的UIActionSheet和U​​IAlertView類。在使用 動作和樣式配置警報控制器後,使用presentViewController:animated:completion:方法顯示它。

除了向用戶顯示消息之外,還可以將 操作與警報控制器相關聯,以便爲用戶提供一種響應方式。 對於使用addAction:方法添加的每個動作,警報控制器配置一個包含動作細節的按鈕。當用戶 點擊該動作時,警報控制器在創建動作對象時執行您提供的塊 。 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];