在任何iPhone应用程序中,请考虑以下顺序(VC=ViewController):
- 显示 VC-A ...用户点击按钮加载 VC-B
- VC-B 现在被推送并显示...用户将滑块从 0 移动到 5 ...然后点击导航栏
- VC-B 被弹出,VC-A 被显示...用户再次点击按钮以加载 VC-B
- VC-B 被推送并显示...但是滑块又回到了 0
发生这种情况是因为上述步骤 2 中的 VC-B 实例与步骤 4 中的 VC-B 实例不同,因此状态丢失。为了避免这种情况,我可以将 VC-B 设为单节点,或者在某处保留对 VC-B 的强引用并重用它,而不是创建一个新实例。
当我从笔尖加载 VC 时,此逻辑曾经很好地工作,因为我会在代码中手动创建 VC 的实例。对于情节提要,这不起作用,因为它是自动创建实例的 segue。那么,我怎样才能确保我重复使用我的 VC?
我尝试了以下技巧来维护单声:
- (id) initWithCoder:(NSCoder *)aDecoder{
if(instance==nil){
NSLog(@"LMHomeViewController init called");
instance = [super initWithCoder:aDecoder];
super.screenType = [NSNumber numberWithInt:home_screen];
}
return instance;
}
但是我遇到了运行时错误:
Terminating app due to uncaught exception 'NSGenericException', reason: 'This coder requires that replaced objects be returned from initWithCoder:'
这里有什么建议吗?我的兴趣是在用户在导航树中来回移动时维护 VC 的状态。
注意:在我的情况下,状态是UIWebView,因此不可能保持其状态。
使用NSUserDefaults
的情况 - 在viewWillAppear
上读取状态,在viewWillDisappear
上写出来,(以及其他任何合适的地方)
在任何情况下,MVC 最好保留在模型中,而不是视图层次结构中。因此,如果不是 NSUserDefaults,请考虑只需要存储状态数据的单一实例。
另一个想法。 如果你确实想保留 ViewController 对象 - 不要使用情节提要 segue。在属性中保留强引用并使用
[self.navigationController pushViewController:self.persistingViewController];
persistingViewController
访问器可以在第一轮中延迟实例化视图控制器。只要保留引用,就可以重用:
- (UIViewController*) persistingViewController
{
if (!_persistingViewController) {
UIStoryboard *story = [UIStoryboard storyboardWithName:@"MainStoryBoard" bundle:nil];
_persistingViewController = [story instantiateViewControllerWithIdentifier:@"myViewController"];
}
return self.persistingViewController
}