Простой протокол делегирования iOS не работает с передачей строк между контроллерами представления
У меня есть простая проблема, и я просто не могу понять, почему она не работает.
У меня есть панель вкладок с одним представлением таблицы (Timeline) для основного приложения и один для настроек. Если пользователь нажимает на вкладку настроек, у него есть возможность выбрать тему в виде другого табличного представления с несколькими ячейками, представляющими темы.
Если пользователь нажимает на тему "Черный", я хочу, чтобы другой вид таблицы на панели вкладок изменил тему.
Я не беспокоюсь о реализации темы; Кажется, у меня возникли проблемы с протоколом делегирования, хотя я и следовал тем же шагам, которые я выполнял для других применений протоколов делегирования в моем приложении.
Вот мое Табличное Представление для Тем:
// .h
@class SelectThemesTableViewController;
@protocol SelectThemesTableViewControllerDelegate <NSObject>
- (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme;
@end
@interface SelectThemesTableViewController : UITableViewController
@property (nonatomic, weak) id <SelectThemesTableViewControllerDelegate> delegate;
@property (nonatomic, strong) NSString *selectedTheme;
// .m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
self.selectedTheme = selectedCell.textLabel.text;
[self.delegate selectThemesTableViewController:self didSelectCell:self.selectedTheme];
NSLog(@"The value of the selected cell is %@", self.selectedTheme);
}
В главном табличном представлении, где я хочу передать строку:
// .h
@property (nonatomic, strong) NSString *selectedTheme;
// .m
@interface TimelineTableViewController () <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, NSFetchedResultsControllerDelegate, SelectThemesTableViewControllerDelegate>
@end
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
SelectThemesTableViewController *selectThemesTableViewController = [[SelectThemesTableViewController alloc] init];
selectThemesTableViewController.delegate = self;
NSLog(@"What is this value %@", self.selectedTheme);
if ([self.selectedTheme isEqualToString:@"Black"])
{
NSLog(@"The value is %@", self.selectedTheme);
}
else
{
NSLog(@"Nope");
}
}
// Here in the viewWillAppear, I'm clearly setting the delegate but the self.selectedTheme is always nil.
// Delegate method in the Timeline Table view:
- (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme
{
self.selectedTheme = selectedTheme;
NSLog(@"String = %@", self.selectedTheme);
// The selectedTheme is always nil here
}
Я установил точки останова и проследил за трассировкой, но в то время как в themeTableView NSLog показывает мне, что я выбираю "черную" ячейку, когда делегирование происходит на временной шкале, оно всегда равно нулю.
Я использую сгруппированное табличное представление с настраиваемой статической ячейкой (так что, насколько я понимаю, нет необходимости в cellForRowAtIndexPath для ThemesTableView, есть?
Обновление: SelectThemesTableViewController
В раскадровке SelectThemesTableViewController формируется как переход (push) на вкладке "Контроллер табличного представления настроек". Итак, у меня есть две вкладки в панели вкладок; первая - это временная шкала, а вторая - SettingsTableViewController. Это встроено в контроллер навигации. Первая ячейка в табличном представлении называется "Темы", и после нажатия на нее происходит переход (push) к SelectThemesTableViewController. Я нигде не готовлю ForSegue, но это заставляет меня думать, что, возможно, я должен быть?
Что мне не хватает? Любая помощь будет принята с благодарностью!
3 ответа
Так как вы используете оба контроллера в панели вкладок, то нет никакой возможности установить делегирование друг другу. Вместо этого вы можете просто обновить NSUserDefaults именем выбранной темы в SelectThemesTableViewController внутри метода делегата didSelectRow, а когда пользователь снова нажмет на первую вкладку, просто проверьте значение NSUserDefault в viewWillAppear, метод TimelineTableViewController и обновите пользовательский интерфейс в соответствии со значением.
// .h
@interface SelectThemesTableViewController : UITableViewController
@property (nonatomic, strong) NSString *selectedTheme;
@end
// .m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
self.selectedTheme = selectedCell.textLabel.text;
[[NSUserDefaults standardUserDefaults] setObject:self.selectedTheme forKey:@"Theme"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(@"The value of the selected cell is %@", self.selectedTheme);
}
------------------------------------------------------------------------------------
// .h
@property (nonatomic, strong) NSString *selectedTheme;
// .m
@interface TimelineTableViewController () <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, NSFetchedResultsControllerDelegate>
@end
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.selectedTheme = [[NSUserDefaults standardUserDefaults] objectForKey:@"Theme"];
NSLog(@"What is this value %@", self.selectedTheme);
if ([self.selectedTheme isEqualToString:@"Black"])
{
NSLog(@"The value is %@", self.selectedTheme);
}
else
{
NSLog(@"Nope");
}
}
ОБНОВЛЕНО для раскадровки
Хорошо, вы не упоминали, что используете раскадровки. Вы не должны нигде создавать контроллер представления
Ваша Подготовка должна выглядеть примерно так...
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//The string needs to be whatever you've set up as the identifier in storyboard
if ([segue.identifier isEqualToString:@"themes"]) {
SelectThemesTableViewController * themeSelector = (SelectThemesTableViewController *) segue.destinationViewController;
themeSelector.delegate = self;
}
}
В протоколе делегата нет ошибки. Это проблема с настройкой вашего делегата. Вы создаете отдельный контроллер представления и назначаете его делегата как самого себя. Это не тот контроллер вида, который отображается, когда нажимается кнопка настройки. Чтобы разрешить этот метод настройки делегата и добавить следующий код в свой SelectThemesTableViewController. Он должен работать.
// assume that first view controller in Tabbar view controller is TimelineTableViewController
//Or else specify correct index of view controller when assigning to delegate.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.delegate = self.tabBarController.viewControllers[0];
}