(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 ViewController
s 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 NavigationController
s, 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 UITabBarController
s 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!
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)
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With