当用户切换到另一个程序后又返回时,原始程序的视图将被另一个程序的新视图替换。所以当用户切换回原来的程序时,viewDidLoad会被第二次调用吗?viewDidLoad多久调用一次?
我问这个,因为如果是这种情况,那么放置在viewDidLoad中的初始化代码将在用户每次来回切换屏幕时执行。而这可能会导致正在重置的意见和失去用户的未完成的作品...
当用户切换到另一个程序后又返回时,原始程序的视图将被另一个程序的新视图替换。所以当用户切换回原来的程序时,viewDidLoad会被第二次调用吗?viewDidLoad多久调用一次?
我问这个,因为如果是这种情况,那么放置在viewDidLoad中的初始化代码将在用户每次来回切换屏幕时执行。而这可能会导致正在重置的意见和失去用户的未完成的作品...
不要在viewDidLoad
做视图控制器初始化。这是一个常见的错误。
对于东西是加载视图控制器时,应该只发生一次,做到在控制器的init方法,像这样:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:bundleOrNil]))
{
//do your initialisation here
}
return self;
}
的initWithNibName:bundle:
方法被称为之前的画面从加载笔尖,并且在视图控制器的使用寿命中仅调用一次。
控制器的视图可以在控制器的使用寿命期间多次加载和卸载,并且每次都会调用。只要不在屏幕上,它可能会被卸载,通常如果内存不足的话。
如果你设置了viewDidLoad
(例如,以编程方式添加子视图)的东西,你应该总是在viewDidUnload
中再次取消它们。
将viewDidLoad
和viewDidUnload
想象为像视图控制器的视图属性的init/dealloc。对于与视图相关的内容,请在这些方法中创建并释放它。对于与控制器本身相关的内容,请在initWithNibName
和dealloc
中创建并释放它。
UPDATE:在iOS 6和后,viewDidUnload
不会被调用任何更多(除非视图被明确设置为nil中的代码),等等viewDidLoad
通常只进行一次在一个视图控制器的寿命称为。这使得建议不太重要,但这仍然是最佳实践,如果您需要支持iOS 5及更早版本,仍然是必要的。
更新2:如果您加载从故事板视图控制器(也就是现在推荐的做法),而不是编程方式创建它,然后initWithNibName:bundle:
不会被调用。改为使用initWithCoder:
或awakeFromNib
来初始化您的控制器。
-viewDidLoad
将被调用一次,每当视图控制器需要加载其视图层次结构。显然,这将在控制器首次访问其视图时发生。如果视图控制器稍后卸载其视图,则在下次加载视图时将再次调用-viewDidLoad
。视图控制器不会因为隐藏视图而卸载其视图,但如果内存开始变慢,它可能会这样做。
视图控制器应该知道其视图的状态,并且可以根据需要在其-viewDidLoad
方法中设置它们。不应该使用视图来存储状态 - 不应该因为视图被卸载而不可挽回地丢失。
那么当用户切换回原来的程序时,会第二次调用 viewDidLoad?
(以上是从OP)
在这种情况下,有两种方法被称为:
- (void)applicationWillEnterForeground:(UIApplication *)application;
重新打开转到后台运行的应用程序(从任务管理器或跳板再次)
解锁设备,该应用程序处于活动状态时被锁定。
- (void)applicationDidBecomeActive:(UIApplication *)application
后打电话
通知中心解雇
任务管理器撤职(双击Home键&双再次点击)
感谢您的详细解答... – Stanley 2012-02-04 01:30:20
@Nick洛克伍德提供优秀的信息,但也有一些事情要记住。
首先,如果视图控制器是从nib文件或故事板实例化的,则不会调用initWithNibName:bundle:
。在这种情况下,调用initWithCoder:
和awakeFromNib
。这种情况在iOS上有点不常见,但随着故事板的增加,现在视图控制器绕过initWithNibName:bundle:
更为常见。
我建议把非UI初始化代码在一个单独的方法(我称之为我的setup
)和来自initWithNibName:bundle:
和awakeFromNib
调用它。但是,只有在初始化只运行一次非常重要的时候,我才会这样做。否则,我把它放在viewWillAppear:
尽可能延迟加载。其次,你不应该做任何在init...
或awakeFromNib
中引用self.view
的东西。你永远不应该参考self.view
,直到调用viewDidLoad
(否则你会强制nib文件比需要的更早加载)。与UI有关的事情应该在viewDidLoad
(如果它们与设置视图有关)或viewWillAppear:
(如果它们与配置视图(即,用数据加载它们)有关)。
所以我的方式通常设置这些东西了:
@implementation
- (void)setup {
// Non-UI initialization goes here. It will only ever be called once.
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
if ((self = [super initWithNibName:nibName bundle:bundle])) {
[self setup];
}
return self;
}
- (void)awakeFromNib {
[self setup];
}
- (void)viewDidLoad {
// Any UI-related configuration goes here. It may be called multiple times,
// but each time it is called, `self.view` will be freshly loaded from the nib
// file.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Set all IBOutlets to `nil` here.
// Drop any lazy-load data that you didn't drop in viewWillDisappear:
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Most data loading should go here to make sure the view matches the model
// every time it's put on the screen. This is also a good place to observe
// notifications and KVO, and to setup timers.
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Unregister from notifications and KVO here (balancing viewWillAppear:).
// Stop timers.
// This is a good place to tidy things up, free memory, save things to
// the model, etc.
}
- (void)dealloc {
// standard release stuff if non-ARC
[[NSNotificationCenter defaultCenter] removeObvserver:self]; // If you observed anything
// Stop timers.
// Don't unregister KVO here. Observe and remove KVO in viewWill(Dis)appear.
}
@end
感谢您的评论。 – Stanley 2012-02-04 01:31:15
评论是不正确的。每次你的视图控制器的视图被加载时,它都会被调用,而不仅仅是第一次。 – 2012-02-04 01:35:43
感谢您的更正... – Stanley 2012-02-04 01:48:51