Как удалить одноразовые переменные класса из кода Objective-C? - PullRequest
6 голосов
/ 25 января 2010

Я пишу некоторый код Objective-C и часто сталкиваюсь с ситуацией, когда мне приходится использовать переменную класса для хранения значения для однократного использования. После употребления он мне больше не нужен. Для меня хранение этого значения в переменной класса похоже на запах кода. На самом деле значение должно быть передано в качестве параметра для методов, которые я использую.

Обычно я сталкиваюсь с этим, когда принимаю делегатов. Например, у меня есть пользовательский интерфейс с несколькими кнопками, которые используются для загрузки и отображения UIActionSheet, когда они касаются. Этот лист действий содержит средство выбора даты, которое устанавливает значение для UILabel при отклонении листа действий.

- (IBAction)setPurchaseDateTapped {
    self.activeField = purchaseDate;
    [self loadDatePickerActionSheet:@"Edit Purchase Date"];
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    self.activeField.text = value_from_UIActionSheet;
}

Как вы можете видеть здесь, обратный вызов actionSheet clickedButtonAtIndex не позволяет мне передавать activeField, поэтому я должен использовать переменную класса. Кажется более правильным написать это:

- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
    parameter.text = value_from_UIActionSheet;
}

Я полагаю (?), Что я могу создать подкласс делегата UIActionSheet и UIActionSheet и добавить необходимые мне подписи, но, опять же, это требует больше усилий, чем оно того стоит.

Итак, мой вопрос: как лучше всего делать то, что я пытаюсь сделать?

Я не обязательно хочу изменять созданный мной интерфейс выбора даты / листа действий (хотя, если есть более удобный шаблон для установки нескольких дат в UIView при одновременном исключении DatePicker, я полностью уши.)

Ответы [ 3 ]

3 голосов
/ 25 января 2010

В этом случае, я думаю, что простой подкласс UIActionSheet будет правильным путем:

@interface SpecialActionSheet : UIActionSheet
{
    id parameter;
}
@property (assign) id parameter;
@end

@implementation SpecialActionSheet
@synthesize parameter;
@end

Этого должно быть достаточно, так как все, что вы хотите сделать, это сохранить в actionSheet параметр. Теперь ваш код может выглядеть следующим образом:

- (void)loadDatePickerActionSheet:(NSString *)caption forField:(UITextField *)field {
    //...
    datePickerActionSheet.parameter = field;
}

- (IBAction)setPurchaseDateTapped {
    [self loadDatePickerActionSheet:@"Edit Purchase Date" forField:purchaseDate];
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    UITextField * field = ((SpecialActionSheet *)actionSheet).parameter;
    field.text = value_from_UIActionSheet;
}
2 голосов
/ 25 января 2010

Другое решение - использовать ассоциативное хранилище.

UIActionSheet может уже иметь его. Вы можете проверить это по

[myActionSheet setValue:@"test value" forKey:@"testKey];
NSLog(@"%@",[myActionSheet valueForKey:@"testKey];

Ассоциативное хранилище довольно изящно, если не чрезмерно.

2 голосов
/ 25 января 2010

Мой обычный подход в таких ситуациях - использовать свойство tag в UIAlertViews и переключаться на него (это целое число). Это не так хорошо, как иметь строку или что-то, что нужно передать, но если у вас есть несколько предупреждений, это простой способ избавиться от неоднозначности. Например:

...
actionSheet.tag = [fields indexOfObject: self.activeField];
...        //fields is an NSArray of all the field objects I might have on the screen


- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
    [[field objectAtIndex: actionSheet.tag] setText: value_from_UIActionSheet];
}
...