我有一个无法与状态还原一起正常使用的应用程序。以前确实如此,但是当我开始离开情节提要时,它停止了。

我的应用程序以LoginViewController开头,这是情节提要中的起始视图控制器。如果登录成功,则尝试将两个FolderViewController添加到导航控制器。这样一来,可见文件夹就已经深了一层。这是通过以下代码完成的:

UINavigationController  *foldersController = [[UINavigationController alloc] initWithNavigationBarClass:nil toolbarClass:nil];
foldersController.restorationIdentifier = @"FolderNavigationController";

FolderViewController *root = [storyboard instantiateViewControllerWithIdentifier:@"FolderView"];
root.folderId = 0;
FolderViewController *fvc = [storyboard instantiateViewControllerWithIdentifier:@"FolderView"];
fvc.folderId = 1;

[foldersController setViewControllers:@[root, fvc] animated:YES];
[self presentViewController:foldersController animated:YES completion:nil];


FolderViewController具有此awakeFromNib

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.restorationClass = [self class];   // If we don't have this, then viewControllerWithRestorationIdentifierPath won't be called.
}


在情节提要中,FolderViewController设置了restorationIdentifier。当我按“主页”按钮时,该应用程序已暂停。我在FolderViewController中的恢复调用被调用:

// This is being called
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super encodeRestorableStateWithCoder:coder];
    [coder encodeInt64:self.folderId forKey:@"folderId"];
}


现在的问题是当我尝试还原时。我在调试器中停止该应用程序,然后再次启动。这将启动恢复过程。

首先,调用viewControllerWithRestorationIdentifierPath:coder:LoginViewController。这不会做太多,它的使用是可选的。我尝试将其删除,但没有任何不良影响。

+ (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
    LoginViewController* vc;
    UIStoryboard* sb = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey];
    if (sb)
    {
        vc = (LoginViewController *)[sb instantiateViewControllerWithIdentifier:@"LoginViewController"];
        vc.restorationIdentifier = [identifierComponents lastObject];
        vc.restorationClass = [LoginViewController class];
    }
    return vc;
}


接下来,我的viewControllerWithRestorationIdentifierPath:coder:FolderViewController称为:

// This is being called
+ (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
    FolderViewController* vc;
    UIStoryboard* sb = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey];
    if (sb)
    {
        vc = (FolderViewController *)[sb instantiateViewControllerWithIdentifier:@"FolderView"];
        vc.restorationIdentifier = [identifierComponents lastObject];
        vc.restorationClass = [FolderViewController class];
        vc.folderId = [coder decodeInt32ForKey:@"folderId"];
    }
    return vc;
}


我以前也有一个decodeRestorableStateWithCoder:,它确实被调用了。但是,由于是在viewControllerWithRestorationIdentifierPath:coder:中设置的,因此无需保留它。

所有这些事情都被称为适当的次数。但最后,在LoginViewController中显示的唯一视图控制器。为什么没有显示我的FolderViewController。我需要在LoginViewController中做一些遗漏的设置来附加以前手动添加的视图控制器吗?

编辑

阅读了似乎相关的http://aplus.rs/2013/state-restoration-for-modal-view-controllers/之后,我将以下代码添加到了App委托中:

- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
    if ([identifierComponents.lastObject isEqualToString:@"FolderNavigationController"])
    {
        UINavigationController *nc = [[UINavigationController alloc] init];
        nc.restorationIdentifier = @"FolderNavigationController";
        return nc;
    }
    else
        return nil;
}


我认为该应用现在更幸福,但仍无法正确还原。现在,我在日志中收到此错误:


  警告:尝试在视图不在窗口层次结构中的上显示!


不一样

最佳答案

我有类似的问题。我的视图控制器堆栈非常简单:带有表视图的根视图->一些详细信息视图->一些编辑详细信息视图。没有导航视图,视图是模态的。而且它没有用。

原来,问题是,根视图控制器中的viewControllerWithRestorationIdentifierPath()应该看起来像这样:

+ (UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents
                                                             coder:(NSCoder *)coder
{
        NSDictionary *myRestorableObj = [coder decodeObjectForKey:@"myRestorableObj"];

        // @todo Add more sanity checks for internal structures of @ myRestorableObj here
        if (myRestorableObj == nil)
                return nil;

        return [[UIApplication sharedApplication] delegate].window.rootViewController;
}


实例化新的根视图控制器是错误的。它创建视图控制器的新堆栈,堆栈中存储的子级视图控制器不属于该视图控制器。

通常,应使用以下代码创建所有其他子级视图控制器:

UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MyChildViewController"];


希望这可以帮助。

07-24 12:27