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 等的顺序,我必须更改案例顺序。这个索引的东西不是一个好的解决方案。

我试图想出一种方法来做到这一点并变得独立于索引,但没有得到任何令人满意的解决方案。使用 buttonTitleAtIndex 也不够好,因为我的应用程序是本地化的,我必须为每个条目测试 n 个标题。有什么建议么?

4

4 回答 4

5

由于我创建了一个基于块的UIAlertViewand版本UIActionSheet,我个人再也不会使用基于委托的 Apple 版本。您可以在我的 GitHub 存储库
中下载我的OHActionSheetOHAlertView类。

因为它们基于completionBlock模式,所以它们更具可读性(所有代码都在同一个地方,多个没有共同的委托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/case使用 NSStrings

请注意,在if/else完成处理程序中测试的 otherButtons 部分中,您可以测试idxusing aswitch/case或使用 my ObjcSwitchcategory,这将允许您编写类似switch/case代码但 for 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
];

编辑:现在最新的 LLVM 编译器支持新的“Object Literals”语法,您可以像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 回答
0

很抱歉为这样一个老问题添加了一个迟到的答案,但谷歌搜索“UIActionSheet 块”会导致这里出现,所以我想我会与你分享我写的这个简单的块实现。

https://github.com/freak4pc/UIActionSheet-Blocks

干杯!

于 2013-09-29T10:46:54.597 回答
0

老问题,但在 iOS 8 中,新UIAlertController类允许您UIAlertAction使用块创建 s:

let alertController = UIAlertController(title: "Pancakes", message: "Do you like them with:", preferredStyle: .ActionSheet)

alertController.addAction(UIAlertAction(title: "Maple Syrup", style: .Default, handler: { (alert) -> Void in
    println("Picked syrup")
}))

alertController.addAction(UIAlertAction(title: "Jam", style: .Default, handler: { (alert) -> Void in
    println("Jam? eh?")
}))

alertController.addAction(UIAlertAction(title: "I HATE PANCAKES", style: .Destructive, handler: { (alert) -> Void in
    println("You monster.")
}))
于 2014-12-04T21:43:52.850 回答