web-dev-qa-db-ja.com

UIAlertViewのボタンのイベントハンドラーを作成する方法

Obj cに次のような警告ビューがあるとしましょう

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"szMsg" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:@"download"];
        [alert show];
        [alert release];

これで、アラートビューに2つのボタン([OK]と[ダウンロード])ができました。ダウンロードボタンのイベントハンドラーを作成する方法は?

21
Ravi

最初に、以下のようにヘッダーファイルにUIAlertViewDelegateを追加する必要があります。

ヘッダーファイル(.h)

@interface YourViewController : UIViewController<UIAlertViewDelegate> 

実装ファイル(.m)

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"szMsg" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:@"download"];
        [alert show];
        [alert release];

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0)
    {
        //Code for OK button
    }
    if (buttonIndex == 1)
    {
        //Code for download button
    }
}
45
Chetan Bhalara

ほとんどのiOSデバイスには、ブロックをサポートするしっかりしたバージョンがあり、ボタンの押下を処理するために不器用なコールバックAPIを使用することは時代遅れです。ブロックは進むべき道です、例えば GitHubのLambda Alertクラス を参照してください:

CCAlertView *alert = [[CCAlertView alloc]
    initWithTitle:@"Test Alert"
    message:@"See if the thing works."];
[alert addButtonWithTitle:@"Foo" block:^{ NSLog(@"Foo"); }];
[alert addButtonWithTitle:@"Bar" block:^{ NSLog(@"Bar"); }];
[alert addButtonWithTitle:@"Cancel" block:NULL];
[alert show];
5
zoul

既知のUIAlertViewsを宣言します。

UIAlertView *alertLogout=[[UIAlertView alloc]initWithTitle:@"Title" message:@"Stop Application?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil]; 

[alertLogout show]; 

[alertLogout release];

デリゲートを自分に設定し、このメソッドを実装します。

-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(actionSheet== alertLogout) {//alertLogout
        if (buttonIndex == 0){

        }else if(buttonIndex==1){

        }
    }else if (actionSheet==alertComment) {//alertComment
        if (buttonIndex==0) {

        }
    }
}
2

StackとGuillermo Ortegaの答えは、おそらくUIAlertViewのカップルで使用するものですが、10では使用しません。私は BlocksKit を使用しています。これは、魂が示唆したLambdaのものと同じです。これも良いオプションですが、ネストされたブロックが多すぎると、そのデメリットが明らかになります(別のライブラリに依存しているという事実は別として)。

複数のものを処理する通常の方法は、ハンドラーオブジェクトを持つことです。 (_@interface MyAlertViewDelegate : NSObject <UIAlertViewDelegate> @end_)そのオブジェクトをアラートビューのデリゲートにし、少なくともアラートビューが閉じられるまでオブジェクトが有効であることを確認します。これは確かにうまくいきますが、やり過ぎかもしれません...

以下は私が思いついたものです。 IMOのほうが簡単で、サードパーティのライブラリやUIAlertViewごとのivarは必要ありません。現在のUIAlertViewが実行するアクションを格納するための1つの追加オブジェクト(@property (nonatomic, strong) NSArray *modalActions

UIAlertViewを表示し、それに応じて反応する

_UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle
                                                    message:@"Blah blah"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:b1, b2, b3, nil];
// Add one selector/action per button at the proper index
self.modalActions = @[
                   [NSNull null], // Because indexes of UIAlertView buttons start at 1
                   NSStringFromSelector(@selector(actionForAlertViewButton1)),
                   NSStringFromSelector(@selector(actionForAlertViewButton2)),
                   NSStringFromSelector(@selector(actionForAlertViewButton3))];
[alertView show];
_

デリゲートメソッド:

_- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (alertView.cancelButtonIndex != buttonIndex) {
        [self performModalActionAtIndex:buttonIndex];
    }
}
_

実際にアクションを実行する部分:

_- (void)performModalActionAtIndex:(NSInteger)index
{
    if (-1 < index && index < self.modalActions.count &&
        [self.modalActions[index] isKindOfClass:[NSString class]]) {
        SEL action = NSSelectorFromString(self.modalActions[index]);
        NSLog(@"action: %@", self.modalActions[index]);
        if ([self respondsToSelector:action]) {
// There is a situation with performSelector: in ARC.
// http://stackoverflow.com/questions/7017281/
#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self performSelector:action];
#pragma clang diagnostic pop
    }
    self.modalActions = nil;
}
_

UIActionSheetsでも再利用可能

_UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title
                                                         delegate:self
                                                cancelButtonTitle:cancelButton  
                                           destructiveButtonTitle:nil 
                                                otherButtonTitles:button1, button2, button3, nil];
// Similarly, add one action per button at the proper index
self.modalActions = @[
                    NSStringFromSelector(@selector(actionForActionSheetButton1)),
                    NSStringFromSelector(@selector(actionForActionSheetButton2)),
                    NSStringFromSelector(@selector(actionForActionSheetButton3))];
_

デリゲートメソッド:

_- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (actionSheet.cancelButtonIndex != buttonIndex) {
        [self performModalActionAtIndex:buttonIndex];
    }
}
_

これが機能する理由:

これには2つの理由があります。

まず、デリゲートを同時に持つ2つのUIAlertViewを表示することはありません。 (IMOすべきではない、見栄えが悪い)。 2番目に、私の場合(ケースの90%として)、アクションのターゲットは常に同じオブジェクトです(この場合:self)。上記の条件を満たしていない場合でも、いくつかの変更を加えてこのアプローチを使用できます。

  • 2つ以上のUIAlerViewsまたはUIActionSheetsを同時に表示する場合(iPadで可能)で辞書を使用して、特定のUIAlertView/UIActionSheetに関連付けられたアクションの1つの配列を保存します。

  • アクションのターゲットがselfでない場合、ペア(ターゲットとアクション)を配列に格納する必要があります。 (UIButtonsをシミュレートするもの_addTarget:action:..._)。

どちらの場合でも、ターゲットやUIActionSheet/UIAlertViewを格納するには、_[NSValue valueWithNonretainedObject:]_が便利になるはずです:)

2
nacho4d
First of all you declare UIAlertViewDelegate in .h file after put below code in .m file

- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex 
{

   if (buttonIndex == 1) 
    {
         //put button action which you want.
    }
}
1
Nikunj Jadav

UIAlertViewDelegateを実装し、デリゲートメソッドを利用する

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
  if(buttonIndex == 0) {
    // Do something
  }
  else {
   // Do something
  }
}
0
visakh7

swift:この小さなコードブロックを使用できます

    let alert = UIAlertController(title: "Alert", message: "This is an alert message", preferredStyle: UIAlertControllerStyle.Alert)

    let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {(action:UIAlertAction) in print("This is in alert block")
    })

    alert.addAction(action)
    self.presentViewController(alert, animated: true, completion: nil)
0
Mr. Tann
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"Data Saved" message:@"Choose more photos" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:Nil];
        [alertView show];
        [alertView release];


-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if(buttonIndex==0)
    {
        [self dismissModalViewControllerAnimated:YES];
    }
}
0
user2131610