我有一个无法与状态还原一起正常使用的应用程序。以前确实如此,但是当我开始离开情节提要时,它停止了。
我的应用程序以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"];
希望这可以帮助。