Селекторы в программировании iPhone - PullRequest
2 голосов
/ 12 июня 2009

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

Сам вид состоит из метки, текстового поля и двух кнопок на панели навигации: «отмена» и «ОК».

Когда пользователь нажимает «Отмена», я просто возвращаюсь к контроллеру корневого представления.

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

Я пытался реализовать это следующим образом:

Заголовок:

@interface UserInputViewController : UIViewController {
    UILabel *textLabel;

    UITextField *textField;

    SEL OKButtonAction;
}

-(NSString*) getEnteredText;

-(UserInputViewController*) initWithTitle: (NSString*)title Text: (NSString*)text andOKButtonSelector: (SEL) OKButtonSelector;

@end

Реализация:

@implementation UserInputViewController

-(UserInputViewController*) initWithTitle: (NSString*)title Text: (NSString*)text andOKButtonSelector: (SEL) OKButtonSelector
{
    self = [self init];
    self.title = title;

    OKButtonAction = OKButtonSelector;

    textLabel = [ [UILabel alloc] initWithFrame: CGRectMake(20, 20, 280, 50)];
    [textLabel setText: text];
    [ [self view] addSubview: textLabel];

    textField = [ [UITextField alloc] initWithFrame: CGRectMake(20, 100, 280, 50)];
    [ [self view] addSubview: textField];

    return self;
}

-(NSString*) getEnteredText
{
    return [textField text];
}

-(void) popToRootViewController
{
    [ [self navigationController] popToRootViewControllerAnimated: YES ];
}

-(void) popToRootWithOKAction
{
    [ [self navigationController] popToRootViewControllerAnimated: YES ];
    [self performSelector: OKButtonAction];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    //Cancel button
    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedString(@"cancel button", @"") style: UIBarButtonSystemItemCancel target: self action: @selector(popToRootViewController) ];


    [ [self navigationItem] setLeftBarButtonItem: cancelButton animated: NO];
    [cancelButton release];

    //OK button
    UIBarButtonItem *OKButton = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedString(@"ok button", @"") style: UIBarButtonSystemItemSave target: self action: @selector(popToRootWithOKAction) ];

    [ [self navigationItem] setRightBarButtonItem: OKButton animated: NO];
    [OKButton release];

}

А вот методы контроллера корневого представления:

-(void) OKButtonAction
{
    NSLog(@"text: %@", [newProfileDialog getEnteredText]);
    [newProfileDialog release];
}

-(void) add_clicked {
    newProfileDialog = [ [UserInputViewController alloc] initWithTitle: @"User name" Text: @"Please enter a new user name:" andOKButtonSelector: @selector(OKButtonAction)];

    [ [self navigationController] pushViewController: newProfileDialog animated: YES];
}

Но когда я скомпилировал его и нажал кнопку OK в режиме просмотра, я получил исключение.

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

Как мне достичь этой цели?

Спасибо.

Ответы [ 3 ]

1 голос
/ 12 июня 2009

То, что вы пытаетесь сделать, называется «делегирование» - действие кнопки OK делегируется другому объекту, в данном случае корневому контроллеру. Попробуйте изменить инициализатор контроллера вида следующим образом:

-(UserInputViewController*) initWithTitle:(NSString*)title Text:(NSString*)text delegate:(id)delegate;

Сохранение делегата в переменной экземпляра (нет необходимости его сохранять) и в popToRootWithOKAction call:

if([delegate respondsToSelector:@selector(OKButtonAction)])
    [delegate performSelector:@selector(OKButtonAction)];

Методы делегирования даже не нужно объявлять в файле .h вашего корневого контроллера. В заголовочный файл UserInputViewController просто добавьте второй @interface:

@interface NSObject (UserInputViewControllerDelegate)
    -(void)OKButtonAction;
@end
1 голос
/ 12 июня 2009

Я бы рекомендовал прочитать раздел о селекторах в документе Objective-C Programming Language на сайте Apple.

Если вы не занимаетесь тщательным самоанализом, нет особых причин фактически объявлять селектор в качестве переменной. Когда это требуется, используйте директиву @selector(), чтобы создать ее.

1 голос
/ 12 июня 2009

[self executeAction: OKButtonAction] вызовет селектор OKBUttonAction для вашего объекта. Скорее всего, вы хотите позвонить делегату. Пока это будет работать:

[[self.navigationController rootViewController] executeSelector: OKButtonAction];

Это не так, как это делают большинство фреймворков. Два подхода, которые я бы рекомендовал:

  • Добавить идентификатор цели; переменная экземпляра, и передайте это в свой метод init. Затем вы можете использовать [делегат executeSelector: OKButtonAction]. Это отделяет контроллер представления от корневого контроллера представления, позволяя использовать этот контроллер представления и в других обстоятельствах.
  • Вместо «цели» я бы также рассмотрел использование делегата и протокола вместо селектора. Это дает вам строго сформулированные методы, такие как методы, найденные в других делегатах, таких как UITableViewDelegate.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...