Как вызвать реализацию суперкласса метода, который принимает переменное число аргументов, как в [UIAlertView initWithTitle ...]? - PullRequest
4 голосов
/ 01 апреля 2011

Библиотека разработчика OS X показывает, как создать метод, который принимает переменное число аргументов, в следующей технической статье: http://developer.apple.com/library/mac/#qa/qa1405/_index.html.

Я пытаюсь выяснить, возможно ли разделить существующую реализацию метода, которая принимает переменные аргументы, и вызвать реализацию суперкласса.

Используя UIActionSheet в качестве примера, посмотрите на код ниже. Вызов метода initWithTitle суперкласса передает только первый 'otherButtonTitle'. Я не знаю, как передать оставшиеся строки, содержащиеся в списке аргументов переменной.

// MyActionSheet.m

- (id)initWithTitle:(NSString *)title
           delegate:(id < UIActionSheetDelegate >)delegate
  cancelButtonTitle:(NSString *)cancelButtonTitle
destructiveButtonTitle:(NSString *)destructiveButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    // this calls the superclass initWithTitle: method but does not
    // pass NIL terminated list of strings
    self = [super initWithTitle:title
                       delegate:delegate
              cancelButtonTitle:cancelButtonTitle
         destructiveButtonTitle:destructiveButtonTitle
              otherButtonTitles:otherButtonTitles, nil];
    if (self) {
        // custom initialization
    }
    return self;
}

Я могу получить аргументы, используя va_list, va_start, va_end, но не знаю, как передать их в метод суперкласса.

В случае, если у кого-нибудь возникнет искушение сказать мне, что я могу сделать это по-другому (например, не передавайте переменные args, но используйте va_list, va_start, va_end для создания массива строк и вызывайте addButtonWithTitle: несколько раз, я Я знаю, что могу это сделать. Я использовал UIActionSheet в качестве примера. Есть и другие случаи, когда была бы полезна возможность подкласса метода с переменными аргументами, и я хотел бы узнать, как сделать именно то, что я просил, если это возможно .

спасибо!

Ответы [ 3 ]

6 голосов
/ 01 апреля 2011

У ряда классов в Какао есть методы, которые принимают переменное число аргументов. В большинстве случаев эти классы также будут иметь эквивалентный метод, который принимает va_list. Это возможно только в том случае, если предлагаемый класс предоставляет один из этих методов. Например, + [NSString stringWithFormat: ...] принимает переменное количество аргументов. Какао предоставляет - [NSString initWithFormat: arguments:] где параметр arguments является va_list. Это позволяет вам делать следующее:

- (void)setContentsWithFormat:(NSString *)formatString, ... {
    [contents autorelease];

    va_list args;
    va_start(args, formatString);
    contents = [[NSString alloc] initWithFormat:formatString arguments:args];
    va_end(args);
}

Параметр va_list позволяет нам передавать наш собственный список аргументов переменных в метод Какао, чтобы метод Какао мог обрабатывать аргументы.

Однако, поскольку UIAlertView не предоставляет API-интерфейс va_list, возможно, самый чистый способ - повторные вызовы addButtonWithTitle:

2 голосов
/ 01 апреля 2011

Вы не можете.Поддержка переменных в Objective-C, по сути, поддерживает C, и, как вы, возможно, уже знаете, нет (переносимого) способа правильно настроить стек для вызова функции с переменным числом.

Если разработчик суперклассабыл на мяче, будет параллельная функция, которая принимает аргумент va_list или NSArray, который вы можете вызвать вместо этого.Если нет, то вам обычно не везет.

В этом конкретном случае вы можете вызвать конструктор суперкласса с помощью nil для всех кнопок, а затем использовать addButtonWithTitle:, cancelButtonIndex и т. Д.для настройки кнопок «вручную».

0 голосов
/ 01 апреля 2011

Если вы не можете сделать это должным образом, вы всегда можете сделать это:

id arg1 = ...; // nil or 1st arg
id arg2 = ...; // nil or 2nd arg
id arg3 = ...; // nil or 3rd arg
id arg4 = ...; // nil or 4th arg
// etc.

self = [super initWithTitle:title
                   delegate:delegate
          cancelButtonTitle:cancelButtonTitle
     destructiveButtonTitle:destructiveButtonTitle
          otherButtonTitles:arg1,arg2,arg3,arg4,/*etc*/ nil];

безобразно, как ад, но это сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...