Раскадровка Две сцены. Перенос текста из UITableViewCell в сцене 2 в UILabel в сцене 1

У меня есть две сцены в раскадровке. Поскольку мне не разрешено загружать изображения (новый пользователь), назовем их Сцена 1 и Сцена 2.

Сцена 1: UITableViewCell с UILabel. Когда эта ячейка выбрана, вы переходите к сцене 2.
Сцена 2: Предоставляет пользователям варианты для выбора в UITableView. После выбора опции рядом с выбранной ячейкой UITableViewCell ставится галочка.

Как мне получить его, когда вы нажимаете кнопку «Сохранить» в сцене 2, она берет текст из выбранного UITableViewCell в сцене 2 и возвращает пользователя к сцене 1, а также заполняет UILabel текстом из сцены 2?

Я использовал раскадровку для создания UITableViews. Каждая ячейка имеет свой класс. Спасибо.


person user1107173    schedule 31.12.2012    source источник


Ответы (1)


Используйте шаблон проектирования делегирования, чтобы позволить двум объектам взаимодействовать друг с другом (ссылка на Apple).

В основном:

  1. Создайте свойство в сцене 2, называемое делегатом.
  2. Создайте протокол в сцене 2, определяющий методы, которые должен определить делегат сцены 2.
  3. Перед переходом от сцены 1 к сцене 2 установите сцену 1 в качестве делегата сцены 2.
  4. Когда ячейка выбрана в сцене 2, отправьте сообщение делегату сцены 2, чтобы сообщить делегату о выборе.
  5. Разрешить делегату обрабатывать выбор и закрыть сцену 2 после того, как выбор сделан.

И в качестве примера:

Интерфейс сцены 2

@class LabelSelectionTableViewController

@protocol LabelSelectionTableViewControllerDelegate
  - (void)labelSelectionTableViewController:(LabelSelectionTableViewController *)labelSelectionTableViewController didSelectOption:(NSString *)option;
@end

@interface LabelSelectionTableViewController : UITableViewController
  @property (nonatomic, strong) id <LabelSelectionTableViewControllerDelegate> delegate;
@end

Реализация сцены 2

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];   
  [self.delegate labelSelectionTableViewController:self didSelectOption:cell.textLabel.text];
}

Реализация сцены 1

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([segue.destinationViewController isKindOfClass:[LabelSelectionTableViewController class]] == YES)
  {
    ((LabelSelectionTableViewController *)segue.destinationViewController).delegate = self;
  }
}

// a selection was made in scene 2
- (void)labelSelectionTableViewController:(LabelSelectionTableViewController *)labelSelectionTableViewController didSelectOption:(NSString *)option
{
  // update the model based on the option selected, if any    
  [self dismissViewControllerAnimated:YES completion:nil];
}
person Bill    schedule 31.12.2012
comment
Спасибо за быстрый ответ. Поэтому я следовал вашему коду. Три ошибки: Сцена 1 = STletsMeet Сцена 2 = STStartTransport Ошибка 1 находится в STStartTransport.h: ‹code› @ протокол STStartTransportDelegate ‹NSObject› - (void)stStartTransport:(STStartTransport *)stStartTransport didSelectOption:(NSString *)option; // Я получаю сообщение об ошибке в этой строке: ! Ожидается тип @end // Остальная часть кода в этом файле в порядке, как показано ниже: @ interface STStartTransport : UITableViewController @ свойство (неатомарное, сильное) id ‹STStartTransportDelegate› delegate; @ конец ‹/код› - person user1107173; 01.01.2013
comment
Без проблем. Это ошибка компилятора, потому что компилятор еще не знает о типе STStartTransport (т. е. объявление интерфейса следует за объявлением протокола). Добавьте @class STStartTransport перед объявлением протокола, как показано в отредактированной версии выше. Надеюсь, это поможет. - person Bill; 01.01.2013
comment
Ошибка: 2 и 3 находятся в одном и том же коде prepareForSeque. STLetsMeet.m - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.destinationViewController isKindOfClass:[STStartTransport]] == YES) // Ошибка 2: Ожидаемый идентификатор { ((STStartTransport *) segue.destinationViewController).delegate = self; // Ошибка 3: Присвоение 'id‹STStartTransportDelegate›' из несовместимого типа 'STLetsMeet *const_strong' } } Наконец, вы упомянули следующий шаг: 5. Перед переходом от сцены 1 к сцене 2 установите сцену 1 в качестве делегата сцены 2. - person user1107173; 01.01.2013
comment
Я использую раскадровку и использовал Control Drag для вызова Push из сцены 1 в сцену 2. Я не использовал (и я недостаточно уверен, чтобы знать, как) использовать prepareForSeque для вызова сцен. Не уверен, что это имеет значение?‹/br› Я нуд (я почти уверен, что это очевидно). Я прочитал 3 книги по iOS, и я все еще борюсь. Большое спасибо за вашу помощь.‹/br› - person user1107173; 01.01.2013
comment
Кстати, добавление исправленной ошибки @class 1. Спасибо! - person user1107173; 01.01.2013
comment
Ошибка 2 связана с тем, что вам нужно вернуть объект класса для STStartTransport. В частности, это должно быть «isKindOfClass: [класс STStartTransport]». Для ошибки 3, скорее всего, вам нужно объявить STLetsMeet как STStartTransportDelegate. В объявлении интерфейса STStartTransport (файл .h или .m) добавьте «‹STStartTransportDelegate›» после объявления интерфейса (например, «@interface STLetsMeet() ‹STStartTransportDelegate›»). - person Bill; 01.01.2013
comment
Не волнуйтесь. Даже если вы используете раскадровки, вам нужно будет вызывать prepareForSegue всякий раз, когда вам нужно передать некоторую информацию в контроллер представления, который будет создан. В этом случае вам нужно сообщить новому контроллеру представления, что вы являетесь его делегатом, чтобы он мог сообщить вам, когда была выбрана метка. - person Bill; 01.01.2013
comment
Ошибка 2 исправлена. Спасибо. Однако ошибка 3 остается. Даже после того, как я добавил ‹STStartTransportDelegate› в объявление интерфейса. @interface STStartTransport : UITableViewController ‹STStartTransportDelegate› Я только что заметил еще одно предупреждение в неполной реализации STStartTransport.m. Метод 'stStartTransportation:didSelectOption: в протоколе не реализован. - person user1107173; 01.01.2013
comment
Симулятор теперь работает. STletsmeet (сцена 1), когда я нажимаю на ячейку, я попадаю в STStartTransport (сцена 2). Однако теперь программа дает сбой: *** Завершение приложения из-за необработанного исключения «NSInvalidArgumentException», причина: «-[STLesMeet stStartTransport:didSelectOption:]: нераспознанный селектор отправлен в экземпляр 0x8864e10» *** Первый стек вызовов броска: - person user1107173; 01.01.2013
comment
Программа кэширует, когда я выбираю одну из ячеек. Мне нужен текст из выбранной ячейки обратно в STletsMeet UILabel. - person user1107173; 01.01.2013
comment
Для ошибки 3 и новой, это говорит о том, что STletsMeet не реализовал требуемый метод в протоколе, который вы создали. Убедитесь, что вы определили - (void)stStartTransport:(STStartTransport *)stStartTransport didSelectOption:(NSString *)option в STLetsMeet. Здесь вы управляете выбором метки и отклоняете STStartTransport. Текст из выбранной ячейки будет в аргументе «опция». - person Bill; 01.01.2013
comment
Я определил его следующим образом: - (void)stStartTransport:(STStartTransport *)stStartTransport didSelectOption:(NSString *)option { startTransportLabel.text = option; [самостоятельно уволитьViewControllerAnimated: ДА, завершение: ноль]; } Вы были правы, была опечатка. Программа перестала вылетать. Ошибка 3 остается. И после выбора Сцена 2 не возвращается к Сцене 1. Нужно ли к чему-то привязывать кнопку Сохранить? - person user1107173; 01.01.2013
comment
Итак, я заметил, что если я нажму назад после выбора, метка пользовательского интерфейса появится с правильным текстом! Спасибо. Я CTR+нажал кнопку сохранения со второй сцены на первую. Но когда я нажимаю кнопку «Сохранить», UILabel не отображает текст. Это похоже на то, когда я нажимаю «Сохранить», я получаю совершенно новую сцену 1, и ничего не сохраняется. Когда я нажимаю Назад, все сохраняется. - person user1107173; 01.01.2013
comment
Рад слышать, что есть прогресс. Похоже, вы не хотите, чтобы STStartTransport закрывался, пока вы не нажмете «Сохранить», а не просто щелкнете по ячейке. В этом случае вы должны отправить сообщение stStartTransport:didSelectOption в методе, связанном с действием сохранения, а не в tableView:didSelectRowAtIndexPath. - person Bill; 01.01.2013
comment
Я нахожусь в районе залива Сан-Франциско, и жена хочет, чтобы я отключился от компьютера (уже почти 12). Я попробую это в AM и вернусь к вам. Кстати, я многому научился сегодня, благодаря вам! С новым годом! - person user1107173; 01.01.2013
comment
Чтобы текст был выделен таким образом, просто посмотрите на выделенную ячейку в таблице. Получите путь индекса через tableView:indexPathForSelectedRow, а затем ячейку через tableView:cellForRowAtIndexPath. - person Bill; 01.01.2013
comment
Привет. В IBAction для кнопки «Сохранить» я использовал следующий код (и удалил его из tableView:didSelectRowAtIndexPath). { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; UITableViewCell *selectedCell = [self.tableView cellForRowAtIndexPath:indexPath]; [self.delegate stStartTransport:self didSelectOption:selectedCell.textLabel.text];} Кнопка «Сохранить» работает, но вызывает новую сцену 1 (STLetsMeet), а заголовок кнопки «Назад» — это заголовок исходной сцены 1. И текст не появляется. - person user1107173; 02.01.2013
comment
Мне нужна кнопка «Сохранить», чтобы сделать то, что раньше делала «Отмена». Вместо того, чтобы двигаться вперед с новой сценой 1, мне нужно, чтобы она вернулась к исходной сцене 1 с UILabel, заполненным текстом выбранной ячейки. И когда я нажимаю «Отмена», мне нужно проигнорировать любой выбор и вернуться к исходной сцене 1 с пустой UILabel. - person user1107173; 02.01.2013
comment
Сожалеем, что у вас возникли эти проблемы, но я не смогу отлаживать ваш код. Обзор этих уроков может помочь . После изучения этих тем, я уверен, вы сможете исправить эти ошибки. - person Bill; 02.01.2013
comment
Ok. Я понял это. Итак, я оставил UITableViewCell *selectedCell = [self.tableView cellForRowAtIndexPath:indexPath]; [self.delegate stStartTransport: self didSelectOption: selectedCell.textLabel.text]; Под - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath. В первой сцене мне пришлось создать Exit Segue -(IBAction)done:(UIStoryboardSegue *)segue { [self rejectViewControllerAnimated:YES завершения:NULL]; } То, что работает с кнопкой «Готово». - person user1107173; 03.01.2013
comment
Для кнопки «Назад» в сцене 2 я вошел в - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender и изменил название UILabel обратно на исходное. Я думаю, что может быть лучший способ отменить любые изменения, но пока это работает. Заняло полдня, но я разобрался. Спасибо за вашу помощь еще раз! - person user1107173; 03.01.2013
comment
Также, чтобы избавиться от предупреждений. Мне пришлось добавить следующее в сцену 1.h. @interface STLetsMeet : UITableViewController ‹Scene2CustomProtocol›, а также импортировать Scene2.h - person user1107173; 03.01.2013