25

私はObjective Cにかなり慣れていないので、UIAlertViewのUIAlertViewDelegate引数としてブロックまたはセレクターを使用できるかどうかを理解しようとしています-そしてどちらがより適切ですか?

次のことを試しましたが、うまくいかないので、正しい軌道に乗っているかどうかわかりませんか?

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

ありがとう!

4

11 に答える 11

28

いい案。ここにあります。アラート ビューと同様ですが、アラートが閉じられたときに呼び出されるブロック プロパティが追加されます。(編集 - 元の回答以来、このコードを単純化しました。これが私が現在プロジェクトで使用しているものです)

//  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];
于 2012-04-10T02:52:39.517 に答える
2

Appleのドキュメントにあるように、そのアプローチにはUIAlertControllerを使用する必要があります

UIAlertController オブジェクトは、ユーザーに警告メッセージを表示します。このクラスは、アラートを表示するための UIActionSheet および UIAlertView クラスを置き換えます。必要なアクションとスタイルでアラート コントローラーを構成したら、presentViewController:animated:completion: メソッドを使用して表示します。

ユーザーにメッセージを表示するだけでなく、アラート コントローラーにアクションを関連付けて、ユーザーが応答する方法を提供できます。addAction: メソッドを使用して追加するアクションごとに、アラート コントローラはアクションの詳細を含むボタンを構成します。ユーザーがそのアクションをタップすると、アクション オブジェクトの作成時に指定したブロックがアラート コントローラーによって実行されます。 アップル ドキュメント。

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];
于 2015-11-17T06:33:20.990 に答える
1

素晴らしいアイデア。カテゴリパターンを使用して、サブクラスを使用せず、UIAlertView を直接呼び出して、まさにあなたのアイデアを完成させました。次の手順に従ってください。

  1. .h ファイルのカテゴリ UIAlertView

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

それが役立つことを願っています。

于 2015-01-07T08:36:18.163 に答える
1

github でこのUIAlertView-Blocksカテゴリを確認してください。私はこれを使用していますが、うまく機能します。

于 2012-04-10T16:53:00.063 に答える
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ます:-)

于 2012-08-25T16:42:19.550 に答える
0

同じことを行う別の便利なライブラリを次に示します。http://bit.ly/ichalrtvw

ここにコード: http://bit.ly/ichalertview

于 2014-08-25T08:53:27.790 に答える
0

Github の UIAlertView-Blocks カテゴリを確認してください。私はこれを書きましたが、非常に使いやすく、うまく機能します。

幸運を。

于 2014-04-14T18:12:45.460 に答える
0

REKitを使用するだけです。BlocksKit に似ていますが、より強力です。

于 2013-02-14T07:38:28.657 に答える
-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];
于 2012-10-31T02:41:31.603 に答える