RespondsToSelector: не работает для делегата

Я новичок в мире iOS и столкнулся с проблемой при попытке передать значение из TableView обратно в домашний контроллер.

Сценарий, над которым я работаю

  1. Домашний контроллер имеет кнопку
  2. Нажатие кнопки открывает список элементов во втором UIViewController
  3. Пользователь выбирает элемент из списка
  4. Выбранный элемент добавляется в другой список на Home Controller

Действительно ценю любые указатели на эту проблему:

Вот как я готовлюсь к Segue on Home

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    UIViewController *destination = segue.destinationViewController;
    if ([destination respondsToSelector:@selector(setDelegate:)]) { 
        [destination setValue:self forKey:@"delegate"];
    }

}

SecondController имеет идентификатор делегата, поэтому я предполагаю, что делегат установлен какrespondsToSelector"возвращает true для" setDelegate "

Теперь в SecondController, когда пользователь выбирает элемент, который я вызываю didSelectRowAtIndexPath & viewWillDisappear методы для установки элемента и исчезновения вида:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    POSAllItemsCell *cell = (POSAllItemsCell *) [tableView cellForRowAtIndexPath:indexPath];

    item = [NSDictionary dictionaryWithObjectsAndKeys:cell.name, @"Name", cell.price, @"Price", cell.code, @"Code", nil];

    [self dismissViewControllerAnimated:YES completion:NULL];

}

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

    if ([delegate respondsToSelector:@selector(setSelection:)]) {
        [delegate setValue:item forKey:@"selection"];
    }
}

Теперь проблема в том, что respondsToSelector за setSelection возвращает false, хотя у меня есть метод setSelection в моем HomeController:

- (void) setSelection:(NSDictionary *)dict {
    if (![dict isEqual:selection]) {
        ......
    }
}

Заранее извиняюсь, если мой вопрос неясен или плохо отформатирован. Кстати это для iOS 5 с Xcode 4.2

2 ответа

Решение

Чтобы делегирование работало, вам нужно настроить его так:

В вашем FirstViewController.h Заголовочный файл, убедитесь, что вы заявляете, что второй контроллер представления соответствует протоколу делегирующего контроллера представления:

@interface FirstViewController : UIViewController <SecondViewControllerDelegate>

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

Тогда у вас есть свой метод делегата, определенный в FirstViewController.m файл:

- (void)setSelection:(NSDictionary *)dict {
    if (![dict isEqual:selection]) {
        ......
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"someSequeIdentifierHere"]) {
        SecondViewController *sv = segue.destinationViewController;
        sv.delegate = self;
    }
}

Вы заметите, что вместо использования UIViewController в prepareForSegue метод, вы должны просто привести его к фактическому контроллеру представления, чтобы вы могли установить свойства для этого. Таким образом, вам не нужно проверять, отвечает ли контроллер представления или нет, так как он имеет delegate свойство определено или нет (в этом случае вам нужно добавить его).

Чтобы настроить свой оригинальный протокол делегата, вы обычно придерживаетесь этого формата в SecondViewController.h файл:

@protocol SecondViewControllerDelegate <NSObject>
- (void)setSelection:(NSDictionary *)dict;
@optional
- (void)someOptionalDelegateMethodHere;
@end

@interface SecondViewController : UIViewController

@property (nonatomic, weak) id <SecondViewControllerDelegate>delegate;

@end

Делегаты почти всегда должны быть слабо определены для ARC.

Затем, когда вы хотите уведомить делегата в SecondViewController.m

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

    if ([self.delegate respondsToSelector:@selector(setSelection:)]) {
        [self.delegate setSelection:item];
    }
}

поскольку delegate определяется как открытое свойство в файле.h, вы можете ссылаться на него как self.delegate или же _delegate но ссылаясь на это как delegate заставляет меня думать, что вы неправильно определили его как частную переменную экземпляра вместо этого.

Единственный раз, когда этот тип шаблона не будет отвечать на respondsToSelector: когда вы не правильно назначаете это delegate на ваш FirstViewController

Надеюсь это поможет!

Попробуй это:

if ([destination respondsToSelector:@selector(setDelegate:)]) { 
    [destination performSelector:@selector(setDelegate:) withObject:self];
}
Другие вопросы по тегам