iOS 7 – viewDidLoad和viewDidAppear之间的区别

很抱歉,这可能不是一个编程问题本身,而是更多的关于iOS生命周期function性质的问题。

我有一个应用程序,我有一个函数,创build四个数组,并通过数据库查询填充它们。 首先,我从viewDidLoad函数中调用函数,但是,无论何时加载视图,视图实际出现之前都需要大约3-4秒的时间。 所以我做的是我创build了一个activityViewIndicator和我的viewDidLoad函数看起来像这样:

 - (void)viewDidLoad:(BOOL)animated{ [super viewDidLoad]; NSLog(@"viewDidLoad Entered"); [self.activityIndicatorView startAnimating]; partInput.delegate = self; brandInput.delegate = self; barcodeInput.delegate = self; itemNameInput.delegate = self; //initializeArrays is the function that initializes the arrays [self initializeArrays]; [self.activityIndicatorView stopAnimating]; } 

但是,这是行不通的,因为viewDidLoad函数在应用程序仍在前一个视图中时被触发。 视图仅在viewDidLoad完成后才显示。 所以我做的是将数组初始化移动到我的viewDidAppear函数,它看起来像:

 - (void)viewDidAppear:(BOOL)animated{ NSLog(@"viewDidAppear loaded successfully"); [self.activityIndicatorView startAnimating]; partInput.delegate = self; brandInput.delegate = self; barcodeInput.delegate = self; itemNameInput.delegate = self; [self initializeArrays]; [self.activityIndicatorView stopAnimating]; } 

但是,当我部署这个,没有任何延迟,使activityIndi​​catorView无用。

我的问题是,为什么在我看来, viewDidLoadviewDidAppear之间有“性能差异”?

请每次按照下面的视图控制器生命周期。 您将以这种方式感到惊讶于您的应用程序的编码和性能。

在这里输入图像描述

我将指出你的苹果文档,因为我认为需要对View Controller生命周期进行更多解释,而不仅仅是回答你的问题。

https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html

最终,你的视图控制器有一个生命周期:

初始化 – 但是你初始化你的视图控制器

viewWillLoad / viewDidLoad – 在构造视图时调用(通过第一次调用通过视图属性检索视图控制器的UIView – 也称为延迟加载)

viewWillAppear:当视图正准备立即出现(animated == NO)或查看转换(animation== YES)时,

viewDidAppear: – 如果视图外观未被取消,视图控制器视图完全显示

viewWillDisappear: – 补充viewWillAppear:

viewDidDisappear: – 补充viewDidAppear:

viewWillUnload / viewDidUnload – 当视图由于内存限制而被卸载时不推荐使用的API(不必担心这些)

dealloc – 视图控制器本身被释放

尽pipe如此,我相信你的问题可能是你的数组初始化阻塞了主线程。 你应该阅读asynchronous编程,但同时你可以做这样的事情:

 - (void)viewDidLoad { [super viewDidLoad]; // other stuff __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ typeof(weakSelf) strongSelf = weakSelf; if (strongSelf) { [strongSelf initializeArraysSynchronously]; dispatch_async(dispatch_get_main_queue(), ^{ strongSelf.doneIntializingArrays = YES; [strongSelf.activityIndicatorView stopAnimating]; }); } }); } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (!self.doneInitializingArrays) { [self.activityIndicatorView startAnimating]; } } 

但是,当您从服务器(或大量数据处理)加载内容时,还必须考虑延迟。 如果你把所有的networking通信打包到viewDidLoad或者viewWillAppear中 ,它们会在用户看到视图之前被执行 – 可能导致你的应用程序被冻结 。 首先向用户展示带有某种活动指标的未填充视图可能是个好主意。 当您完成networking连接时,可能需要一两秒钟(甚至可能会失败 – 谁知道?),则可以使用数据填充视图。 在各种Twitter客户端可以看到关于如何做到这一点的好例子。 例如,当您在Twitterrific中查看作者详细信息页面时,该视图仅在networking查询完成之前显示“正在加载…”。

每次初始化ViewController但Viewdidapper时,ViewDidLoad只调用一次。

activityIndicatorViews只会动起来,如果主线程(UI线程)不忙。 viewDidLoad:viewDidAppear:都在主线程上执行。 如果像你提到的那样, initializeArrays方法不会在单独的线程中执行,那么activityIndicatorViews将永远不会有时间进行animation。

viewDidLoad:和viewDidAppear:之间绝对没有性能差异。 两者都是在主线程上运行的正常function。 如果您的initializeArrays方法需要3秒加载,无论您调用哪种方法,都需要3秒钟的时间。 由于你没有明确地改变线程,所以你调用initializeArrays的任何函数都不会退出,直到完成。

对[self.activityIndi​​catorView startAnimating]的调用将基本上“标记”activityIndi​​catorView,以便主线程上的另一个UI函数将启动它的animation。 (这就是为什么主要或“UI”线程是重要的,因为所有的animation和视觉更新屏幕上的协调)。 所以实际上将获取activityIndi​​cator的函数在initializeArrays完成之前不会被调用,而您已经调用了“stopAnimating”。

尝试这个:

 - (void)viewDidLoad:(BOOL)animated{ [super viewDidLoad]; NSLog(@"viewDidLoad Entered"); [self.activityIndicatorView startAnimating]; partInput.delegate = self; brandInput.delegate = self; barcodeInput.delegate = self; itemNameInput.delegate = self; } - (void)viewDidAppear:(BOOL)animated{ //initializeArrays is the function that initializes the arrays [self initializeArrays]; [self.activityIndicatorView stopAnimating]; } 

视图加载 – 第一种方法,当第一次加载视图时调用,但没有出现在屏幕/窗口上,只加载。

在第一次加载视图时只调用一次。

查看出现 – viewWillAppear调用后,viewDidAppear将被调用。 这意味着视图现在出现在屏幕上。

被调用的次数,因为用户正在从该视图控制器移动到另一个视图控制器并返回。

**

  • 查看生命周期

**

1)ViewDidLoad(仅在第一次加载视图时调用),然后2)ViewWillAppear(将被调用的次数),然后3)ViewDidAppear(将被调用的次数),然后4)ViewWillDisAppear(将被调用的次数次),然后5)ViewDidDisAppear(将被称为次数)