繁体   English   中英

viewDidLoad多久调用一次?

[英]How often is viewDidLoad called?

当用户切换到另一个程序然后再返回时,原始程序的视图将被另一个程序的新视图替换。 那么当用户切换回原始程序时,第二次会调用viewDidLoad吗?

我问这个是因为如果是这种情况,那么每次用户来回切换屏幕时,都会执行viewDidLoad中的初始化代码。 这可能会导致重置视图并丢失用户未完成的作品......

不要在viewDidLoad查看控制器初始化。 这是一个常见的错误。

对于应该只在加载视图控制器时发生一次的东西,在控制器的init方法中执行它,如下所示:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundleOrNil
{
    if ((self = [super initWithNibName:nibNameOrNil bundle:bundleOrNil]))
    {
        //do your initialisation here
    }
    return self;
}

在从nib加载视图之前调用initWithNibName:bundle:方法,并且仅在视图控制器的生命周期中调用一次。

在控制器的生命周期内,控制器的视图可以多次加载和卸载,每次都会调用viewDidLoad 只要它不在屏幕上,通常在内存不足时可以卸载它。

如果你在viewDidLoad设置了东西(例如以编程方式添加子视图),你应该总是在viewDidUnload再次设置它们。

可以将viewDidLoadviewDidUnload视为视图控制器的view属性的init / dealloc。 对于与视图相关的内容,请在这些方法中创建和释放它。 对于与控制器本身相关的内容,请在initWithNibNamedealloc创建并释放它。

更新:在iOS 6及更高版本中,不再调用viewDidUnload (除非在代码中将视图显式设置为nil),因此viewDidLoad通常仅在视图控制器的生命周期中调用一次。 这使得上面的建议不那么重要,但它仍然是最佳实践,如果您需要支持iOS 5及更早版本,仍然是必需的。

更新2:如果从Storyboard(现在是推荐的做法)加载视图控制器而不是以编程方式创建它,则不会调用initWithNibName:bundle: 使用initWithCoder:awakeFromNib来初始化控制器。

@Nick Lockwood提供了极好的信息,但还有一些事情需要记住。

首先,如果视图控制器是从nib文件或故事板实例化的,则不会调用initWithNibName:bundle: . 在这种情况下,会调用initWithCoder:awakeFromNib 这种情况在iOS上有点不常见,但随着故事板的增加,视图控制器绕过initWithNibName:bundle:现在更为常见initWithNibName:bundle: .

我建议将非UI初始化代码放在一个单独的方法中(我称之为我的setup )并从initWithNibName:bundle:awakeFromNib调用它。 但是我只会这样做,如果初始化只运行一次很重要。 否则我把它放在viewWillAppear:尽可能地延迟加载。

其次,你不应该在init...awakeFromNib做任何引用self.view事情。 在调用viewDidLoad之前,你永远不应该引用self.view (否则你将强制加载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

只要视图控制器需要加载其视图层次结构,就会调用-viewDidLoad一次。 显然,这将在控制器第一次访问其视图时发生。 如果视图控制器稍后卸载其视图,则下次加载视图时将再次调用-viewDidLoad 视图控制器不会仅因为视图被隐藏而卸载其视图,但如果内存开始变低则可能会这样做。

视图控制器应该知道其视图的状态,并能够在其-viewDidLoad方法中根据需要进行设置。 视图不应该用于存储状态 - 因为视图被卸载,所以不应该不可避免地丢失任何内容。

那么当用户切换回原始程序时,第二次会调用viewDidLoad吗?

(上面是来自op)

在这些情况下,有两种方法可以调用:

- (void)applicationWillEnterForeground:(UIApplication *)application;

重新打开一个后台应用程序(从任务管理器或再次从跳板)
解锁应用程序处于活动状态时锁定的设备。

- (void)applicationDidBecomeActive:(UIApplication *)application

打完电话后
通知中心解雇
任务经理被解雇(双击主页按钮并再次双击)

来自文档

在视图控制器将其关联的视图加载到内存后调用此方法。

因此,只要视图控制器将其视图加载到内存中,就会调用它。 这可能是第一次加载视图而且从未再次加载,或者每次视图在视图卸载时都可见(由于内存限制等而导致viewDidUnload

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM