iOS 7 - viewDidLoad 和 viewDidAppear 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22214843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS 7 - Difference between viewDidLoad and viewDidAppear
提问by Razgriz
Sorry but this may not be a programming question per se but more of an inquiry over the nature of iOS lifecycle functions.
抱歉,这本身可能不是一个编程问题,而是对 iOS 生命周期函数性质的更多询问。
I have an application where I have a function that creates four arrays and populates them via database queries. At first, I called the function from the viewDidLoad
function, however, whenever the View is loaded, it takes time (around 3-4 seconds) before the view actually appears. So what I did was I created an activityViewIndicator
and my viewDidLoad
function looks something like:
我有一个应用程序,其中有一个函数可以创建四个数组并通过数据库查询填充它们。起初,我从viewDidLoad
函数中调用了该函数,但是,无论何时加载视图,视图实际出现之前都需要时间(大约 3-4 秒)。所以我所做的是我创建了一个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];
}
However this doesn't work since the viewDidLoad
function is triggered when the application is still in the previous View. The View only comes into display after viewDidLoad
is already done. So what I did instead was move the array initialization to my viewDidAppear
function which looks like:
但是,这不起作用,因为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];
}
However, when I deployed this, there was no delay whatsoever, making the activityIndicatorView useless.
但是,当我部署它时,没有任何延迟,使 activityIndicatorView 无用。
My question is, why does it seem to me that there's a "performance difference" between viewDidLoad
and viewDidAppear
?
我的问题是,为什么我觉得viewDidLoad
和之间存在“性能差异” viewDidAppear
?
回答by
Please Follow the below View Controller Life Cycle Every Time. You will be amazed with the coding and performance of your application in this manner.
请每次都遵循以下视图控制器生命周期。您会惊讶于您的应用程序以这种方式的编码和性能。
回答by NSProgrammer
I'm going to point you to Apple's docs because I think there is a need for some more explanation of the View Controller lifecycle than just answering your question as phrased.
我将向您指出 Apple 的文档,因为我认为需要对 View Controller 生命周期进行更多解释,而不仅仅是按措辞回答您的问题。
Ultimately, your view controller has a life cycle:
最终,您的视图控制器有一个生命周期:
init - however you initialize your view controller
init - 但是你初始化你的视图控制器
viewWillLoad/viewDidLoad - called when the view is constructed (via the first call to retrieve the view controller's UIView via it's view property - aka lazy loading)
viewWillLoad/viewDidLoad - 在构建视图时调用(通过第一次调用通过视图属性检索视图控制器的 UIView - 又名延迟加载)
viewWillAppear: - when the view is being prepared to appear either immediately (animated == NO) or view a transition (animated == YES)
viewWillAppear: - 当视图准备立即出现(动画 == NO)或查看过渡(动画 == YES)
viewDidAppear: - if the view appearance wasn't cancelled and the view controller's view fully appears
viewDidAppear: - 如果视图外观没有被取消并且视图控制器的视图完全出现
viewWillDisappear: - complements viewWillAppear:
viewWillDisappear: - 补充 viewWillAppear:
viewDidDisappear: - complements viewDidAppear:
viewDidDisappear: - 补充 viewDidAppear:
viewWillUnload/viewDidUnload - deprecated APIs when the view is unload due to memory constraints (don't worry about these anymore)
viewWillUnload/viewDidUnload - 由于内存限制卸载视图时不推荐使用的 API(不要再担心这些)
dealloc - the view controller itself is being deallocated
dealloc - 视图控制器本身正在被释放
In the end though, I believe your issue may be that you are blocking the main thread with your array initialization. You should read up on asynchronous programming but in the meantime you could do something like this:
最后,我相信您的问题可能是您使用数组初始化阻塞了主线程。您应该阅读异步编程,但同时您可以执行以下操作:
- (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];
}
}
回答by devdavid
There is absolutely no performance difference between viewDidLoad: and viewDidAppear:. Both are normal functions running on the main thread. If your initializeArrays method takes 3 seconds to load, it will take 3 seconds in whichever method you call it. Since you are not explicitly changing threads, any function in which you call initializeArrays will not exit until it's finished.
viewDidLoad: 和 viewDidAppear: 之间绝对没有性能差异。两者都是在主线程上运行的普通函数。如果您的 initializeArrays 方法需要 3 秒才能加载,那么无论您调用它的哪种方法都需要 3 秒。由于您没有显式更改线程,因此您调用 initializeArrays 的任何函数在完成之前都不会退出。
The call to [self.activityIndicatorView startAnimating] will basically "mark" the activityIndicatorView so that another UI function on the main thread will start it animating. (This is why the main or 'UI' thread is important, because all animations and visual updates to the screen are coordinated on it). So the function that will actually get the activityIndicator going doesn't get called until initializeArrays is finished and you have called "stopAnimating" already.
对 [self.activityIndicatorView startAnimating] 的调用基本上将“标记”activityIndicatorView,以便主线程上的另一个 UI 函数将启动它的动画。(这就是为什么主线程或“UI”线程很重要,因为屏幕的所有动画和视觉更新都在其上进行协调)。因此,在 initializeArrays 完成并且您已经调用“stopAnimating”之前,不会调用实际使 activityIndicator 运行的函数。
Try this:
尝试这个:
- (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];
}
回答by Anubhav Giri
View Did Load- First method , which is called when view is loaded first time but not appeared on screen/window, only loaded.
View Did Load- First 方法,在第一次加载视图但未出现在屏幕/窗口上时调用,仅加载。
only called one time when view is loaded first time.
第一次加载视图时只调用一次。
View Did Appear- After viewWillAppear called , viewDidAppear will be called. It means view is appeared on screen now.
View Did Appear- 在调用 viewWillAppear 之后,将调用 viewDidAppear。这意味着视图现在出现在屏幕上。
Called number of times as user is moving from that viewcontroller to another view controller and coming back .
当用户从该视图控制器移动到另一个视图控制器并返回时调用的次数。
**
**
- View Life Cycle
- 查看生命周期
**
**
1)ViewDidLoad (called only when view is loaded first time), then 2)ViewWillAppear (will be called number of times), then 3)ViewDidAppear (will be called number of times), then 4)ViewWillDisAppear (will be called number of times), then 5)ViewDidDisAppear (will be called number of times)
1)ViewDidLoad(仅在第一次加载视图时调用),然后是 2)ViewWillAppear(将被调用的次数),然后是 3)ViewDidAppear(将被调用的次数),然后是 4)ViewWillDisAppear(将被调用的次数)次),然后 5)ViewDidDisAppear(将被调用的次数)
回答by Pandey_Laxman
However, when you are loading things from a server(or heavy data processing), you also have to think about latency. If you pack all of your network communication into viewDidLoador viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freezeof your app. It may be good idea to first show the user an unpopulated view with an activity indicator of some sort. When you are done with your networking, which may take a second or two (or may even fail - who knows?), you can populate the view with your data. Good examples on how this could be done can be seen in various twitter clients. For example, when you view the author detail page in Twitterrific, the view only says "Loading..." until the network queries have completed.
但是,当您从服务器加载东西(或大量数据处理)时,您还必须考虑延迟。如果您将所有网络通信打包到viewDidLoad或viewWillAppear 中,它们将在用户看到视图之前执行 - 可能导致短暂冻结你的应用程序。首先向用户显示带有某种活动指示器的未填充视图可能是个好主意。当您完成网络连接时,这可能需要一两秒钟(甚至可能失败 - 谁知道?),您可以使用您的数据填充视图。可以在各种 twitter 客户端中看到如何做到这一点的好例子。例如,当您在 Twitterrific 中查看作者详细信息页面时,该视图只会显示“正在加载...”,直到网络查询完成。
ViewDidLoad calls only once when you initialized your ViewController but Viewdidapper calls every time.
ViewDidLoad 仅在您初始化 ViewController 时调用一次,但 Viewdidapper 每次都会调用。
回答by ThomasW
The activityIndicatorViews
will only animate if the main thread (the UI thread) is not busy. viewDidLoad:
and viewDidAppear:
are both executed on the main thread. If, as you mention, the initializeArrays
method does not execute in a separate thread, then the activityIndicatorViews
will never have time to animate.
该activityIndicatorViews
如果主线程(UI线程)不忙只会动画。viewDidLoad:
并且viewDidAppear:
都在主线程上执行。如果,正如您所提到的,该initializeArrays
方法不在单独的线程中执行,那么activityIndicatorViews
将永远没有时间进行动画处理。
回答by bsod
For those coding programmatically (without Interface Builder), loadView
is the first available lifecycle method, not viewDidLoad
, and programmatic development often makes more use of loadView
than viewDidLoad
, so keep that in mind. A part of what IB does is write the loadView
for you. IB is just a way to shorten programmatic development but if you want to best understand Cocoa Touch, you should understand it programmatically.
对于那些以编程方式(没有 Interface Builder)编码的人来说,loadView
是第一个可用的生命周期方法,而不是viewDidLoad
,并且程序化开发通常loadView
比使用更多viewDidLoad
,所以请记住这一点。IB 所做的一部分工作是loadView
为您编写。IB 只是一种缩短程序化开发时间的方法,但如果你想最好地理解 Cocoa Touch,你应该以程序化的方式理解它。
loadView
comes first and is where UI elements are typically created, including the view of the view controller itself (which programmatic development must explicitly create). Constraints can be added here but they are not handled until later in the lifecycle.
loadView
首先是 UI 元素通常创建的地方,包括视图控制器本身的视图(程序开发必须显式创建)。可以在此处添加约束,但直到生命周期的后期才会处理它们。
viewDidLoad
is where "logic" is typically made once the UI elements have been established.
viewDidLoad
是在 UI 元素建立后通常会生成“逻辑”的地方。
viewWillAppear
and viewWillLayoutSubviews
are called next right before the UI itself is to construct itself.
viewWillAppear
并且viewWillLayoutSubviews
在 UI 本身构建自身之前被调用 next 。
viewDidLayoutSubviews
is called next and can be called multiple times on the same view controller before it actually appears. This is where auto layout is applied. This is also where the programmer can get a view's safe area values since they are not available before this method.
viewDidLayoutSubviews
被调用 next 并且可以在它实际出现之前在同一个视图控制器上多次调用。这是应用自动布局的地方。这也是程序员可以获得视图安全区域值的地方,因为在此方法之前它们不可用。
viewDidAppear
comes last after the view controller's view has appeared in a view hierarchy.
viewDidAppear
在视图控制器的视图出现在视图层次结构中之后出现。