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]; }
但是,当我部署这个,没有任何延迟,使activityIndicatorView无用。
我的问题是,为什么在我看来, viewDidLoad
和viewDidAppear
之间有“性能差异”?
请每次按照下面的视图控制器生命周期。 您将以这种方式感到惊讶于您的应用程序的编码和性能。
我将指出你的苹果文档,因为我认为需要对View Controller生命周期进行更多解释,而不仅仅是回答你的问题。
最终,你的视图控制器有一个生命周期:
初始化 – 但是你初始化你的视图控制器
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.activityIndicatorView startAnimating]的调用将基本上“标记”activityIndicatorView,以便主线程上的另一个UI函数将启动它的animation。 (这就是为什么主要或“UI”线程是重要的,因为所有的animation和视觉更新屏幕上的协调)。 所以实际上将获取activityIndicator的函数在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(将被称为次数)