Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS State Restoration of UITabBarController Does Not Restore Child View Controllers or Selected Index

(This is my first time asking a question on StackOverflow, so forgive me if there are issues)

My problem comes down to not being able to properly restore the state of a UITabBarController. This is a tab-based application and I am not using Storyboards.

I have opted into state restoration. I have provided all of my custom ViewControllers with unique restoration identifiers and restoration classes in their respective init methods.

As for the UITabBarController, I provide it with a unique restoration identifier when it is created. Because I do not give it a restoration class, I have implemented the following code in the app delegate:

- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder 
{
    UITabBarController *vc = [[UITabBarController alloc] init];

    vc.restorationIdentifier = [identifierComponents lastObject];

    if ([identifierComponents count] == 1) {
        self.window.rootViewController = vc;
    }

    return vc;
}

I have used the same method in other apps to restore the state of NavigationControllers, and everything goes smoothly. However, when I do it for this app with the TabBarController, the application launches with an empty TabBarController (the TabBarController is restored, but it does not restore it's child view controllers).

This isn't a huge shock to me, I suppose that just by nature UITabBarControllers do not keep references to their child view controllers not the selected tab index for state restoration. However, despite many hours searching online, I could not any instructions on how to preserve the state of a TabBarController (without storyboard). Any help on how to do this would be tremendously appreciated.

Again, I'm sorry if I did not provide enough detail or wasn't clear enough. Please just let me know what you need in your answers and I'll provide it. I know I didn't provide much of my code, but I really just need instructions on how to preserve the state of a Tab-based application without storyboards. It does not need to be tailored to my specific case; I will be able to apply the general process myself.

Thanks!

like image 528
Eric Elmoznino Avatar asked Oct 30 '22 23:10

Eric Elmoznino


2 Answers

You need to encode each child's view controller. But iOS docs state that you don't decode these - that bit will happen automagically.

override func encodeRestorableStateWithCoder(coder: NSCoder) {
    coder.encodeObject(child0VC, forKey:"child0VC")
    coder.encodeObject(child1VC, forKey:"child1VC")
    super.encodeRestorableStateWithCoder(coder)
}
like image 77
Carl Avatar answered Nov 09 '22 12:11

Carl


I just ran into this issue too, and since it was my first time implementing the state restoration paradigm, wondered if maybe I was doing something wrong.

In my situation, I'm programmatically creating the view controller hierarchy in application willFinishLaunchingWithOptions (which is before state restoration is executed), based on persistent state (login status, etc.). I have a root tab bar controller for which I wanted to store the selected index (at the least) and I expected the default encodeRestorableState and decodeRestorableState methods to take care of this. They didn't.

So I ended up subclassing UITabBarController just for this purpose. It's in Swift, but I assume you can read it. Add breakpoints to be sure these methods are being called.

class LPTabBarController: UITabBarController
{
    let selectedIndexKey = "selectedIndexKey"

    override func encodeRestorableState(with coder: NSCoder) {
        coder.encode(selectedIndex, forKey: selectedIndexKey)
        super.encodeRestorableState(with: coder)
    }

    override func decodeRestorableState(with coder: NSCoder)
    {
        super.decodeRestorableState(with: coder)
        selectedIndex =  coder.decodeInteger(forKey: selectedIndexKey)
    }
}

As a side note, it is my opinion that NSUserDefaults should not be used for such ephemeral UI state as a selected tab bar index.

like image 28
CloakedEddy Avatar answered Nov 09 '22 12:11

CloakedEddy