我正在尝试在使用iOS 6和故事板的应用程序中实现状态恢复,但我在找到一种方法来防止对重方法的重复调用时遇到问题 .
如果我只是启动应用程序,那么我需要在 viewDidLoad
中设置UI:
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
这在正常的非状态恢复世界中工作正常 . 现在我添加了状态恢复,在恢复了一些属性后,我需要用这些属性更新UI:
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
[super decodeRestorableStateWithCoder:coder];
// restore properties and stuff
// [...]
[self setupUI];
}
那么现在发生的是,首先从 viewDidLoad
调用 setupUI
方法,然后再从 decodeRestorableStateWithCoder:
调用 . 我总是叫't see a method that I can override that' .
这是方法调用的正常顺序:
-
awakeFromNib
-
viewDidLoad
-
viewWillAppear
-
viewDidAppear
使用状态恢复时,这称为:
-
awakeFromNib
-
viewDidLoad
-
decodeRestorableStateWithCoder
-
viewWillAppear
-
viewDidAppear
我无法在 viewWillAppear
中调用 setupUI
,因为每当你回到视图时它也会被执行 .
如果 decodeRestorableStateWithCoder
被称为BEFORE viewDidLoad
会更方便,因为那时你可以使用恢复的属性 . 可悲的是,不是这样的,所以......当我知道我需要在 decodeRestorableStateWithCoder
之后重新做一遍时,我怎么能阻止在 viewDidLoad
中完成工作呢?
7 回答
如果您以编程方式进行状态恢复(即不使用故事板),则可以使用
+ viewControllerWithRestorationIdentifierPath:coder:
,在那里初始化视图控制器并使用编码器所需的任何内容来执行pre-viewDidLoad初始化 .我发现尝试实现状态恢复已经在我的代码中显示出错误的编程实践,比如在_1460656中包含太多内容 . 所以虽然这有效(如果你重新设置你的视图控制器 . 而不是使用标志,将代码片段移动到他们自己的方法并从两个地方调用这些方法 .
有趣的是,解码序列甚至是完全不同的:
它完全有道理 .
感谢@calvinBhai的建议 .
从“编程iOS 9:潜入深入视图,视图控制器和框架”一书386-387页
状态恢复期间已知的事件顺序如下:
application:shouldRestoreApplicationState:
application:viewControllerWithRestorationIdentifierPath:coder:
viewControllerWithRestorationIdentifierPath:coder:
,顺序下行viewDidLoad
,顺序下行;可能与上述内容交错decodeRestorableStateWithCoder:
,顺序下行application:didDecodeRestorableStateWithCoder:
applicationFinishedRestoringState
,顺序下行您仍然不知道
viewWillAppear:
和viewDidAppear:
何时到达,或者viewDidAppear:
是否会到达 . 但是在applicationFinishedRestoringState
中,您可以可靠地完成视图控制器和界面的配置 .是的,如果在
-viewDidLoad
之前调用-decodeRestorableStateWithCoder:
,那确实会更好 . 叹 .我将视图设置代码(取决于可恢复状态)移动到
-viewWillAppear:
并使用了dispatch_once()
,而不是布尔变量:文档指出"views are no longer purged under low-memory conditions" so
dispatch_once
应该在视图控制器的生命周期内是正确的 .加入berbie的回答,
实际流程是:
请注意,在
initWithCoder
内,您需要设置self.restorationClass = [self class];
这将强制调用viewControllerWithRestorationIdentifierPath:coder:
.对MixedCase流程的一次修正(非常有帮助,谢谢),实际的调用流程有点不同:
这是方法调用的正常顺序:
awakeFromNib
viewDidLoad中
viewWillAppear中
viewDidAppear
使用状态恢复时,这称为:
viewControllerWithRestorationIdentifierPath(解码常规启动所需的任何数据)
awakeFromNib
viewDidLoad中
viewWillAppear中
viewDidAppear
decodeRestorableStateWithCoder (解码可恢复状态数据,并设置控制器UI)