1

I am implementing state restoration in my app. The root view controller is a UITabBarController. In each of the tabs I have a UINavigationController with child view controllers. State restoration appears to be working fine in the UITabBarController. The issue is in one of the tabs the UINavigationController's top most child View Controller will not call the restoration method: +viewControllerWithRestorationIdentifierPath:coder:

The navigation controllers root view is always going to be a UITableViewController. Depending on what cell is selected you can push to either a DetailViewController or a ProfileViewController. Everything is setup up correctly in my App Delegate and my storyboards and both of these restoration paths restore just fine:

TabBarController->NavigationController->TableViewController->DetailViewController

or

TabBarController->NavigationController->TableViewController->ProfileViewController

However, you also have the ability to push from the DetailViewController to the ProfileViewController and vice-versa but that's where the restoration fails. The top most view controller fails to restore:

TabBarController->NavigationController->TableViewController->DetailViewController->ProfileViewController (fails)

or

TabBarController->NavigationController->TableViewController->ProfileViewController->DetailViewController (fails)

When setting break points it appears that +viewControllerWithRestorationIdentifierPath:coder: is not being called on the top most view controller. It is being called if it's the first view pushed on top of the table controller, but not on any subsequent views be it either Detail to Profile or Profile to Detail.

The implementation of the ProfileViewController

@interface ProfileViewController () <UIViewControllerRestoration>

@end

@implementation ProfileViewController

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
    ProfileViewController *vc = [[ProfileViewController alloc] initWithNibName:@"ProfileViewController" bundle:nil];
    return vc;
}

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
    [super encodeRestorableStateWithCoder:coder];
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.restorationClass = [self class];
        self.restorationIdentifier = [[NSUUID UUID] UUIDString];
    }
    return self;
}

and the DetailViewController are pretty straight forward:

@interface DetailViewController () <UIViewControllerRestoration>

@end

@implementation DetailViewController

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
    DetailViewController *vc = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    return vc;
}

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
    [super encodeRestorableStateWithCoder:coder];
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.restorationClass = [self class];
        self.restorationIdentifier = [[NSUUID UUID] UUIDString];
    }
    return self;
}

The only thing I can possibly come up with is that the UITabBarController, UINavigationControllers, and UITableViewController all use Storyboards but the Detail and Profile views uses nibs and that there may be an issue where using more than one view controller with a nib on a navigation stack that uses storyboards won't restore properly. Any help would be greatly appreciated :)

4

0 回答 0