#iphone #objective-c #ios #uiactionsheet #variadic-functions
#iPhone #objective-c #iOS #uiactionsheet #переменные-функции
Вопрос:
У меня есть таблица действий с параметрами, которые варьируются в зависимости от обстоятельств. Существует достаточно разных названий кнопок, поэтому я хотел бы сначала создать массив этих названий кнопок, но я не могу понять, как преобразовать это в формат varargs.
Я хочу сделать что-то вроде этого:
NSMutableArray *buttonTitles = [NSMutableArray array];
if (condition1) {
[buttonTitles addObject: @"Do action 1"];
}
if (condition2) {
[buttonTitles addObject: @"Do action 2"];
}
if (condition3) {
[buttonTitles addObject: @"Do action 3"];
}
if (condition4) {
[buttonTitles addObject: @"Do action 4"];
}
UIActionSheet *actionSheet = [[[UIActionSheet alloc] initWithTitle: nil delegate: self cancelButtonTitle: @"Cancel" destructiveButtonTitle: nil otherButtonTitles: buttonTitles] autorelease];
Теперь, очевидно, если бы мне пришлось, я мог бы сделать что-то подобное вместо этого:
UIActionSheet *actionSheet = nil;
if (condition1 amp;amp; condition2 amp;amp; condition3 amp;amp; condition4) {
actionSheet = [[[UIActionSheet alloc] initWithTitle: nil delegate: self cancelButtonTitle: @"Cancel" destructiveButtonTitle: nil otherButtonTitles: @"Do action1", @"Do action2", @"Do action3", @"Do action 4", nil] autorelease];
} else if (condition1 amp;amp; condition2 amp;amp; condition3 amp;amp; !condition4) {
actionSheet = [[[UIActionSheet alloc] initWithTitle: nil delegate: self cancelButtonTitle: @"Cancel" destructiveButtonTitle: nil otherButtonTitles: @"Do action1", @"Do action2", @"Do action3", nil] autorelease];
}
// else ...
// about 14 other cases!
Но это было бы ужасно. Кто-нибудь знает какой-нибудь хороший синтаксический сахар, который мог бы мне помочь?
РЕДАКТИРОВАТЬ: было предложено использовать addButtonWithTitle
, что на первый взгляд выглядит великолепно, к сожалению, это помещает дополнительные кнопки после кнопки отмены, что нежелательно.
Я считаю, что это ошибка в коде Apple, поскольку их документация о addButtonWithTitle
состояниях:
// adds a button with the title. returns the index (0 based) of where it was added. buttons are displayed in the order added except for the
// destructive and cancel button which will be positioned based on HI requirements. buttons cannot be customized.
ПРИВЕТСТВЕННЫЕ требования (собственные рекомендации Apple по пользовательскому интерфейсу) предпочитают кнопку отмены ниже всех других параметров, поэтому я бы сказал, что Apple облажалась. Конечно, это мне не очень помогает, поэтому я вернулся к попытке конвертировать между NSArray и varargs, что я до сих пор не знаю, как это сделать.
Ответ №1:
Вы можете попробовать это
NSMutableArray *buttonTitles = [NSMutableArray array];
if (condition1) {
[buttonTitles addObject: @"Do action 1"];
}
if (condition2) {
[buttonTitles addObject: @"Do action 2"];
}
if (condition3) {
[buttonTitles addObject: @"Do action 3"];
}
if (condition4) {
[buttonTitles addObject: @"Do action 4"];
}
[buttonTitles addObject: @"Cancel"];
UIActionSheet *actionSheet = [[[UIActionSheet alloc] initWithTitle: nil delegate: self cancelButtonTitle: nil destructiveButtonTitle: nil otherButtonTitles: nil] autorelease];
for (NSString *title in buttonTitles) {
[actionSheet addButtonWithTitle: title];
}
[actionSheet setCancelButtonIndex: [buttonTitles count] - 1];
Комментарии:
1. Я думал, что это сработало, но я обнаружил некоторые проблемы с этим, см. Редактирование.
2. Это сработало. Хотя, похоже, не было никакой необходимости возиться с какими-либо дополнительными заголовками.
Ответ №2:
Вариант ответа Химаншу:
UIActionSheet * as = [[UIActionSheet alloc] initWithTitle:@"Share"
delegate:self
cancelButtonTitle:nil /* don't set Cancel title here! */
destructiveButtonTitle:nil
otherButtonTitles:nil];
int cancelButtonIndex = 0; // will remain 0 if no other buttons besides "Cancel"
if ( canShareBySMS )
{
[as addButtonWithTitle:kSMSButtonText];
cancelButtonIndex ;
}
if ( canShareByMail )
{
[as addButtonWithTitle:kEmailButtonText];
cancelButtonIndex ;
}
/* etc. */
// after all other buttons have been added, include Cancel
[as addButtonWithTitle:@"Cancel"];
[as setCancelButtonIndex:cancelButtonIndex];
[as showInView:self.sharingViewController.view];
[as release];
Примечание: ваш метод UIActionSheetDelegate должен проверять заголовки кнопок вместо buttonIndex:
- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex {
if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:kSMSButtonText]) {
//share via sms
}else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:kEmailButtonText]) {
//share via mail
}
}
Я думаю, что ключевая деталь, которую люди упускают, — это установка кнопки отмены в селекторе initWithTitle, вместо того, чтобы добавлять ее после всех других кнопок и указывать внешний вид кнопки отмены, вызывая setCancelButtonIndex: .
Ответ №3:
Почему бы просто не сделать что-то вроде этого:
for (Nstring *button in buttonTitles)
[actionSheet addButtonWithTitle:button];
Комментарии:
1. Я думал, что это сработало, но я обнаружил некоторые проблемы с этим, см. Редактирование.
Ответ №4:
Вот метод, который я пробовал, который, похоже, работает просто отлично. Это работает, если вы хотите добавить дополнительную кнопку в конце кнопок, перед кнопкой «отмена».
NSString * optionalButton = nil;
if (condition4) {
optionalButton = @"Some Additional Option";
}
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:@"Some Title"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Button 1",@"Button 2",@"Button 3",optionalButton, nil];
[actionSheet showInView:self.view];
Кажется, можно добавить дополнительный «ноль» в конце списка кнопок, если ваше условие (condition4) не выполнено.
Я успешно протестировал это на iOS7.