4

UIActionSheetの問題に対する洗練された解決策を見つけようとしています。

私は次のようなUIActionSheetsを使用します:

UIActionSheet * myChoices = [[UIActionSheet alloc]
    initWithTitle:nil
    delegate:self
    cancelButtonTitle:@"cancel"
    destructiveButtonTitle:@"erase"
    otherButtonTitles: @"aaa", @"bbb", @"ccc", @"ddd", nil]; 

問題は、ユーザーが選択したオプションを見つけるために、これを使用する必要があることです。

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

    switch ([actionSheet tag]) {
           case 0: ... 
           case 1: ... 
           case 2: ... 
           case 3: ... 

        }
}

アクションシートでaaa、bbb、cccなどの順序を変更すると、ケースの順序を変更する必要があるため、インデックスに基づくこのケースはひどいものです。このインデックスのものは固溶体としては良くありません。

私はそれを行う方法を想像し、インデックスに依存しないようにしようとしましたが、満足のいく解決策はありませんでした。私のアプリはローカライズされており、エントリごとにn個のタイトルをテストする必要があるため、buttonTitleAtIndexを使用するだけでも十分ではありません。助言がありますか?

4

4 に答える 4

5

と のブロック ベース バージョンを作成したのでUIAlertViewUIActionSheet個人的にはデリゲート ベースの Apple バージョンを二度と使用しません。myとclasses は、私の GitHub リポジトリから
ダウンロードできOHActionSheetOHAlertViewます。

これらはcompletionBlockパターンに基づいているため、より読みやすく (すべてのコードが同じ場所にあり、 multiple の共通デリゲートがないUIActionSheetsなど)、より強力です (ブロックは必要に応じてコンテキストもキャプチャするため)。

NSArray* otherButtons = @[ @"aaa", @"bbb", @"ccc", @"ddd" ];
[OHActionSheet showSheetInView:self.view
                         title:nil
             cancelButtonTitle:@"cancel"
        destructiveButtonTitle:@"erase"
             otherButtonTitles:otherButtons
        completion:^(OHActionSheet* sheet, NSInteger buttonIndex)
 {
   if (buttonIndex == sheet.cancelButtonIndex) {
     // cancel
   } else if (buttonIndex == sheet.destructiveButtonIndex) {
     // erase
   } else {
     NSUInteger idx = buttonIndex - sheet.firstOtherButtonIndex;
     // Some magic here: thanks to the blocks capturing capability,
     // the "otherButtons" array is accessible in the completion block!
     NSString* buttonName = otherButtons[idx];
     // Do whatever you want with idx and buttonName
   }
 }];

追記: switch/caseNSStrings の使い方

if/else完了ハンドラーのテストの otherButtons 部分で、idxa を使用してテストするかswitch/case、 my ObjcSwitchcategoryswitch/caseを使用してテストできることに注意してください。これにより、のようなコードを書くことがNSStringsできますが、あなたOHActionSheetの完了ハンドラ:

NSUInteger idx = buttonIndex - sheet.firstOtherButtonIndex;
NSString* buttonName = otherButtons[idx];
[buttonName switchCase:
   @"aaa", ^{ /* Some code here to execute for the "aaa" button */ },
   @"bbb", ^{ /* Some code here to execute for the "bbb" button */ },
   @"ccc", ^{ /* Some code here to execute for the "ccc" button */ },
   ..., nil
];

EDIT : 最新の LLVM コンパイラが新しい「オブジェクト リテラル」構文をサポートするようになったのでObjcSwitch、NSDictionary のコンパクトな構文を使用するのと同じことができます。

((dispatch_block_t)@{
   @"aaa": ^{ /* Some code here to execute for the "aaa" button */ },
   @"bbb": ^{ /* Some code here to execute for the "bbb" button */ },
   @"ccc": ^{ /* Some code here to execute for the "ccc" button */ },
}[buttonName] ?:^{
       /* Some code here to execute for defaults if no case found above */
})();
于 2012-10-24T18:20:50.100 に答える
3

値の配列を使用して、この問題を (完全に解決するわけではありませんが) 支援したいと考えています。これにより、少なくとも統一されたデータ ソースが得られます。したがって、viewDidLoadなどで値の配列を作成することにより、アクションシートを作成するときに、次のように変更できます。

//where myValuesArray is an array of strings you declared in viewDidLoad
//myValuesArray = [NSArray arrayWithObjects:@"aaa", @"bbb", @"ccc", @"ddd", nil];

UIActionSheet * myChoices = [[UIActionSheet alloc]
    initWithTitle:nil
    delegate:self
    cancelButtonTitle:@"cancel"
    destructiveButtonTitle:@"erase"
    otherButtonTitles:nil];

for(NSString *title in myValuesArray)
{
    [myChoices addButtonWithTitle:@"LMNOP"];
}

次に、 clickedButtonAtIndex で、まったく同じ配列のインデックスをチェックしています。これは、私があなたの選択であると想定しています。これにより、変更を加えたいときに配列を更新することもできます。これが役立つことを願っています。

于 2012-10-24T18:12:39.497 に答える