1

我有一个应用程序在状态恢复时无法正常工作。以前是这样,但是当我开始远离故事板时,它停止了。

我的应用程序以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:的 for myLoginViewController被称为。这并没有多大作用,它的使用是可选的。我试过删除它,我没有任何不良影响。

+ (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:for myFolderViewController被称为:

// 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的 s 不显示。我需要在我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;
}

我认为应用程序现在更快乐,但它仍然没有正确恢复。现在我在我的日志中得到这个错误:

警告:尝试在视图不在窗口层次结构中的 <LoginViewController: 0xbaa1260> 上呈现 <UINavigationController: 0xbaacf50>!

这是不同的东西。

4

2 回答 2

0

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

原来,问题是根视图控制器中的 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"];

希望这可以帮助。

于 2018-06-17T11:24:37.840 回答
-1

您需要为不同的FolderViewController对象分配不同的恢复标识符。

例如:

FolderViewController *folderViewController1 = // initialize object ;
FolderViewController *folderViewController2 = // initialize object ;

folderViewController1. restorationIdentifier = @"folderViewController1";
folderViewController2. restorationIdentifier = @"folderViewController2";

我尝试了上面的代码,它运行良好。

于 2014-10-08T16:01:16.287 回答