Custom Navigation Bar Image applied in each View Controller, not conforming to NSUserDefaults Synchronisation

StackOverflow https://stackoverflow.com/questions/22504046

Frage

I have a tab bar controller, consisting of 3 tabbed Table View Controllers (Timeline, Events and Settings) and I am working with themes.

If the user clicks on Settings, they can click on the "Themes" cell and select from a variety of themes.

Through the use of NSUserDefaults, I'm saving the theme in the didSelectCell of the SelectThemesTableViewController:

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

In the Timeline and Event view controller, I'm setting the background, the navigation bar image and the tab bar images in the viewWillAppear, depending on which cell the user selected like this:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.selectedTheme = [[NSUserDefaults standardUserDefaults] objectForKey:@"Theme"];

    if ([self.selectedTheme isEqualToString:@"Blur"])
    {
        // View Background
        UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Purplepink.png"]];
        self.tableView.backgroundView = backgroundImageView;

        // Navigation Bar
        UIImage *navBackgroundImage = [UIImage imageNamed:@"Purplepinknav.png"];
        [[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];

        // Tab Bar
        UIImage *tabBackground = [[UIImage imageNamed:@"SolidPurple.png"]
                                  resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
        [self.tabBarController.tabBar setBackgroundImage:tabBackground];

    }
    else if ([self.selectedTheme isEqualToString:@"Red Slanted"])
    {
        // View Background
        UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"RedSlanted.png"]];
        self.tableView.backgroundView = backgroundImageView;

        // Navigation Bar
        UIImage *navBackgroundImage = [UIImage imageNamed:@"RedSlantedNav.png"];
        [[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];

        // Tab Bar
        UIImage *tabBackground = [[UIImage imageNamed:@"RedSlantedTab.png"]
                                  resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
        [self.tabBarController.tabBar setBackgroundImage:tabBackground];

    }

    else if ([self.selectedTheme isEqualToString:@"Twirl"])
    {
        // View Background
        UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Twirl.png"]];
        self.tableView.backgroundView = backgroundImageView;

        // Navigation Bar
        UIImage *navBackgroundImage = [UIImage imageNamed:@"ReddishBlackNav.png"];
        [[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];

        // Tab Bar
        UIImage *tabBackground = [[UIImage imageNamed:@"ReddishBlackTab.png"]
                                  resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
        [self.tabBarController.tabBar setBackgroundImage:tabBackground];
    }

When I set the theme in the SelectTheme, it works and when I go to Timeline Table View, the theme is fully applied with the background, navigation bar and with the tab bar image. If I exit the app and go back in, everything is still there.

However, the problem is: if I kill off the app from the multi-tasking on the simulator or my device and reopen my app, the background and tab bar is what I last set it as, but the Navigation Bar goes back to the default applied in the App Delegate. If I change to another tab and back to the Timeline, the navigation bar changes to the selected navigation before, but the problem is that initial view which loads up the default Nav Bar rather than the selected and if I change the tab and go back to the Timeline tab, it then shows again.

I have in the viewDidDisappear:

- (void)viewWillDisappear:(BOOL)animated
{
    UIImage *navBackgroundImage = [UIImage imageNamed:@"purplynav.png"];
    [[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];
    UIImage *tabBackgroundImage = [UIImage imageNamed:@"purplytab.png"];
    [[UITabBar appearance] setBackgroundImage:tabBackgroundImage];

}

If I remove this viewDidAppear code, the same thing happens. Am I missing something? Why is the navigation bar not conforming to the NSUserDefaults?

The AppDelegate is below:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"Is this getting called?");
    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
    UIImage *navBackgroundImage = [UIImage imageNamed:@"purplynav.png"];
    [[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];
    UIImage *tabBackgroundImage = [UIImage imageNamed:@"purplytab.png"];
    [[UITabBar appearance] setBackgroundImage:tabBackgroundImage];
    ...
}

EDIT: I have added some logging as per the comment. The NSLog in the didFinishLaunchingWithOptions in the AppDelegate always gets run first. Right after this, the viewWillAppear of the Timeline Table View (the initial view controller) gets called with the NSLog in there.

This explains why the navigation bar goes back to the default the very first time the application is launched after it was killed from the multitasking (or not opened for hours). However, I do not necessarily need to set the code in the AppDelegate. At first, the App had no themes and so setting the AppDelegate's Nav bar was important. However now, I want to start the app off with a theme, but when a new theme is selected, to NOT push forward the App Delegate's Nav Bar the very first time the app is run after being killed.

Any assistance on this would be greatly appreciated.

War es hilfreich?

Lösung

Trim down and simplify your solution so that you configure all of the theme based UI using UIAppearance proxy in 2 places:

  1. The app delegate - using the stored settings (best if this is a call to your theme manager)
  2. The theme manager - using the newly stored settings

In this way your theme code is contained and organised and you always have the appropriate theme applied (instead of some default).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top