Простой протокол делегирования 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];
}
Другие вопросы по тегам