Question

I have what appears to be a simple problem and I just cannot figure out why it isn't working.

I have a tab bar with one table view (Timeline) for the main app and one for the settings. If the user clicks on the settings tab, they have the chance of selecting a theme which is just in the form of another table view with a number of cells representing themes.

If the user clicks on theme "Black", I want the other Table View in the Tab bar to change theme.

I'm not worried about the theme implementation; I seem to be having issues with my delegation protocol here even though I have followed what I believe to be the same steps that I followed for other uses of delegation protocols in my app.

Here's my Table View for the Themes:

// .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); 
}

In the main table view where I want the string to be passed:

// .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 
}

I have put breakpoints in and followed the trace, but while in the themeTableView, the NSLog shows me selecting the "black" cell, when the delegation happens to the Timeline, it's always nil.

I'm using a grouped table view with a custom static cell (so as far as I understand, there's no need for cellForRowAtIndexPath on the ThemesTableView, is there?

Update: SelectThemesTableViewController

In storyboard, SelectThemesTableViewController is formed as a segue (push) from the Settings Table View Controller tab. So I have two tabs in a tab bar; the first is the Timeline and the second is SettingsTableViewController. This is embedded in a navigation controller. The first cell in the Table view is called "Themes" and upon clicking on that, there is a segue (push) to the SelectThemesTableViewController. I'm not preparingForSegue anywhere, but this gets me thinking that perhaps I should be?

What am I missing? Any assistance would be really appreciated!

Was it helpful?

Solution

As you are using both two controllers in tab bar, So there is no any option to set delegate to each other. Instead what you can do is just update the NSUserDefaults with the selected theme name in SelectThemesTableViewController inside didSelectRow delegate method and when user will again tap on first tab just check the NSUserDefault value in viewWillAppear method of TimelineTableViewController and update the UI as per the value.

  // .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");
        }
    }

OTHER TIPS

UPDATED for storyboard

OK you hadn't mentioned you were using storyboards. You shouldn't be creating a view controller anywhere

Your Prepare needs to look something like this...

-(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;
    }
}

There is no mistake in delegate protocol. It is problem with your delegate setting. You are creating separate view controller and assigning its delegate as self. It is not the view controller which is shown, when setting tab button is pressed. To resolve this delegate setting method and add following code in your SelectThemesTableViewController. It should work.

// 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];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top