20

...ObjectiveCの にいくつかの問題があります。

私は基本的にメソッドをラップしていて、nil終了したリストを受け入れて、同じリストをラップしているメソッドに直接渡したいと思っています。

これが私が持っているものですが、EXC_BAD_ACCESSクラッシュの原因になります。ローカル変数を調べると、渡されたときにotherButtonTitles単に a である場合に表示されますNSStringotherButtonTitles:@"Foo", nil]

+ (void)showWithTitle:(NSString *)title
              message:(NSString *)message
             delegate:(id)delegate
    cancelButtonTitle:(NSString *)cancelButtonTitle
    otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
                                                     message:message
                                                    delegate:delegate
                                           cancelButtonTitle:cancelButtonTitle
                                           otherButtonTitles:otherButtonTitles] autorelease];
    [alert show];
}

nilまったく同じ終了リストを維持しながら、着信引数から発信引数に単純に吸い上げるにはどうすればよいですか?

4

3 に答える 3

39

少なくともあなたがやりたいと思っている方法では、これを行うことはできません。あなたがしたいこと(可変引数を渡す)には、UIAlertViewを受け入れる初期化子が必要va_listです。1つもありません。addButtonWithTitle:ただし、次の方法を使用できます。

+ (void)showWithTitle:(NSString *)title
              message:(NSString *)message
             delegate:(id)delegate
    cancelButtonTitle:(NSString *)cancelButtonTitle
    otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
                                                     message:message
                                                    delegate:delegate
                                           cancelButtonTitle:cancelButtonTitle
                                           otherButtonTitles:nil] autorelease];
    if (otherButtonTitles != nil) {
      [alert addButtonWithTitle:otherButtonTitles];
      va_list args;
      va_start(args, otherButtonTitles);
      NSString * title = nil;
      while(title = va_arg(args,NSString*)) {
          [alert addButtonWithTitle:title];
      }
      va_end(args);
    }

    [alert show];
}

もちろん、これは非常に問題固有のものです。va_list本当の答えは、「パラメーターを持たないメソッド/関数に可変引数リストを暗黙的に渡すことはできません」です。したがって、問題を回避する方法を見つける必要があります。与えられた例では、渡したタイトルで alertView を作成したいと考えていました。幸いなことに、UIAlertViewクラスにはボタンを追加するために繰り返し呼び出すことができるメソッドがあり、それによって同じ全体的な効果が得られます。このメソッドがなければ、運が悪いでしょう。

もう 1 つの非常に厄介なオプションは、可変引数マクロにすることです。可変個引数マクロは次のようになります。

#define SHOW_ALERT(title,msg,del,cancel,other,...) { \
  UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; \
  [_alert show]; \
}

ただし、可変個引数マクロ アプローチを使用しても、これを実行するたびにカスタム マクロが必要になります。それは非常に堅実な代替手段ではありません。

于 2010-02-26T22:42:22.457 に答える
0

NSInvocationオブジェクトを作成するのはどうですか?引数はポインタで渡す必要があるため、ポインタをnilで終了するリストに渡すことができます。

を使用してパラメーターを反復処理しmarg_list()、nilで終了するリストを自分で作成することもできます。

これらは単なる提案です。私はそれらを試していません。

于 2010-02-26T22:34:14.737 に答える
0

これは OP のUIAlertView-wrapping ケースに固有のものであり、iOS7 でのみテストされています: aUIAlertViewが で初期化されotherButtons:nil、そのスタイルがそれに設定されていると、そのデリゲートを呼び出して入力を検証UIAlertViewStylePlainTextInputしないように見えます。alertViewShouldEnableFirstOtherButton:これがバグなのか意図した動作なのかはわかりませんが、驚きを最小限に抑えるという私の原則が破られました。これは次のように再現できます (デリゲートalertViewShouldEnableFirstOtherButton:が実装されていると仮定します)。

UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Title" 
                                             message:@"message" 
                                            delegate:self         
                                   cancelButtonTitle:@"Cancel" 
                                   otherButtonTitles:nil];
[av setAlertViewStyle:UIAlertViewStylePlainTextInput];
[av addButtonWithTitle:@"OK"];
[av show];

UIAlertView は喜んで を受け入れるため、解決策は、上記のように、otherButtonTitles (nil の場合もある) でotherButtons:nil初期化UIAlertViewし、可変引数を反復処理することです。

+ (void)showWithTitle:(NSString *)title
              message:(NSString *)message
             delegate:(id)delegate
    cancelButtonTitle:(NSString *)cancelButtonTitle
    otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
                                                     message:message
                                                    delegate:delegate
                                           cancelButtonTitle:cancelButtonTitle
                                           otherButtonTitles:otherButtonTitles] autorelease];

    // add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here

    if (otherButtonTitles != nil) {
        va_list args;
        va_start(args, otherButtonTitles);
        NSString * title = nil;
        while(title = va_arg(args,NSString*)) {
            [alert addButtonWithTitle:title];
        }
        va_end(args);
    }

    [alert show];
}
于 2013-10-29T09:50:33.493 に答える