Простой протокол делегата iOS не работает с передачей строк между контроллерами представления

У меня есть то, что кажется простой проблемой, и я просто не могу понять, почему она не работает.

У меня есть панель вкладок с одним табличным представлением (временная шкала) для основного приложения и одним для настроек. Если пользователь нажимает на вкладку настроек, у него есть возможность выбрать тему, которая представлена ​​в виде другого табличного представления с несколькими ячейками, представляющими темы.

Если пользователь нажимает на тему «Черный», я хочу, чтобы другое табличное представление на панели вкладок изменило тему.

Я не беспокоюсь о реализации темы; Кажется, у меня возникли проблемы с моим протоколом делегирования здесь, хотя я выполнил то, что я считаю теми же шагами, что и для других применений протоколов делегирования в моем приложении.

Вот мой вид таблицы для тем:

// .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 показывает, что я выбираю «черную» ячейку, когда делегирование происходит на временной шкале, оно всегда равно нулю.

Я использую сгруппированное табличное представление с настраиваемой статической ячейкой (насколько я понимаю, в ThemesTableView нет необходимости в cellForRowAtIndexPath, не так ли?

Обновление: SelectThemesTableViewController

В раскадровке SelectThemesTableViewController формируется как переход (push) с вкладки «Контроллер табличного представления настроек». Итак, у меня есть две вкладки на панели вкладок; первый — это временная шкала, а второй — SettingsTableViewController. Это встроено в навигационный контроллер. Первая ячейка в табличном представлении называется «Темы», и при нажатии на нее происходит переход (нажатие) к SelectThemesTableViewController. Я нигде не готовлюсь к ForSegue, но это наводит меня на мысль, что, возможно, мне следует это сделать?

Что мне не хватает? Любая помощь будет очень признательна!


person amitsbajaj    schedule 18.03.2014    source источник


Ответы (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");
        }
    }
person if-else-switch    schedule 18.03.2014
comment
Это абсолютно сделал это! Большое спасибо, Сэм - если бы я мог проголосовать за него много раз, я бы проголосовал. Используя эту технику, я могу обеспечить согласованность на протяжении всего жизненного цикла приложения, а также когда оно закрывается и отключается от многозадачности. Спасибо вам большое за это. Действительно отличная помощь! - person amitsbajaj; 18.03.2014

ОБНОВЛЕНО для раскадровки

Хорошо, вы не упомянули, что используете раскадровки. Вы не должны создавать контроллер представления в любом месте

Ваша подготовка должна выглядеть примерно так...

-(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;
    }
}
person Flexicoder    schedule 18.03.2014
comment
Большое спасибо @Flexicoder, и это действительно имеет большой смысл. Я внес изменения, но, как ни странно, self.selectedTheme по-прежнему равен нулю. Я собираюсь попробовать поиграть с этим, но я не уверен, что мне не хватает, хотя ваша рекомендация действительно имела смысл ... есть мысли? - person amitsbajaj; 18.03.2014
comment
Думаю, 2 строки назначения должны быть в viewDidLoad, а не viewWillAppear. Вы перезаписываете значения каждый раз, когда возвращаетесь к представлению - person Flexicoder; 18.03.2014
comment
Спасибо @Flexicoder - пробовал, но не работает. Однако я заметил, что метод делегата - (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme на временной шкале никогда не вызывается, потому что NSLog там ( NSLog(@String = %@, self .selectedTheme); никогда не срабатывает. Если я вызываю этот метод из viewDidLoad или viewDIdAppear, он по-прежнему равен нулю, но я всегда думал, что вам не нужно будет специально вызывать это... он все равно должен срабатывать? - person amitsbajaj; 18.03.2014
comment
можете ли вы уточнить свой вопрос о том, как вы представляете SelectThemesTableViewController - вы создаете еще один перед презентацией? вы должны использовать тот, который вы сейчас создаете в viewDidLoad - person Flexicoder; 18.03.2014
comment
Спасибо - я только что обновил вопрос в конце. Вы заставили меня задуматься; Я нигде не делаю prepareForSegue и не знаю, где использовать новый self.selectThemesTableViewController, который сейчас используется в viewDidLoad. Возможно, ссылки нет. Я имею в виду, что у перехода есть идентификатор, но я его ниоткуда не вызываю. Возможно, мне нужно вызвать его из SettingsTableView? - person amitsbajaj; 18.03.2014
comment
большое спасибо за ваше время сегодня утром с этим. Я очень ценю ваши усилия и ответы на многие мои простые вопросы. В приведенном ниже ответе Сэма это работает именно так, как я хотел бы, с NSUserDefaults. Большое спасибо еще раз. - person amitsbajaj; 18.03.2014

В протоколе делегата нет ошибок. Это проблема с настройкой вашего делегата. Вы создаете отдельный контроллер представления и назначаете его делегата как 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];
}
person Rajath Shetty K    schedule 18.03.2014
comment
Спасибо @rajath - с этим кодом в моем SelectThemesTableViewController у меня возникает сбой с завершающим приложением из-за необработанного исключения «NSInvalidArgumentException», причина: «-[UINavigationController selectThemesTableViewController:didSelectCell:]: нераспознанный селектор отправлен экземпляру. Я делаю что-то неправильно с этим кодом? - person amitsbajaj; 18.03.2014
comment
Уважаемый @rajath - большое спасибо, что уделили время ответу, и ответ Сэма ниже помог. Я ценю ваши мысли и усилия с этим, хотя. - person amitsbajaj; 18.03.2014