I am trying to find an elegant solution to UIActionSheet problem.
I use UIActionSheets like this:
UIActionSheet * myChoices = [[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:@"cancel"
destructiveButtonTitle:@"erase"
otherButtonTitles: @"aaa", @"bbb", @"ccc", @"ddd", nil];
the problem is that in order to discover the option selected by the user, I have to use this:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch ([actionSheet tag]) {
case 0: ...
case 1: ...
case 2: ...
case 3: ...
}
}
this case based on index is terrible, because if I change the order of the aaa, bbb, ccc, etc., on the action sheet I have to change the case order. This index stuff is not good as a solid solution.
I have tried to imagine a way to do that and become index independent but did not come any satisfactory solution. Using buttonTitleAtIndex is not good enough too, because my apps are localized and I would have to test for n titles for every entry. Any suggestions?
Since I created a block-based version of UIAlertView
and UIActionSheet
, I personally never use the delegate-based Apple version again.
You can download my OHActionSheet
and OHAlertView
classes in my GitHub repository.
Because they are based on the completionBlock pattern, they are more readable (all the code is at the same place, no common delegate for multiple UIActionSheets
, …), and more powerful (because blocks also capture their context as needed).
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
on NSStringsNote that in the otherButtons part of the if/else
test in your completion handler, you can then either test for the idx
using a switch/case
, or use my ObjcSwitch
category, that will allow you to write switch/case
-like code but for NSStrings
, so you can have a code like this in your OHActionSheet
's completion handler:
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 : Now that the latest LLVM compiler supports the new "Object Literals" syntax, you can do the same as ObjcSwitch
using the compact syntax of an 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 */
})();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With