ios7 - viewDidLoad和viewDidAppear之间的差异

时间:2022-09-04 15:17:07

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之间存在“性能差异”?

6 个解决方案

#1


215  

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.

请按照下面的视图控制器的生命周期。您将对应用程序的编码和性能感到惊讶。

ios7 - viewDidLoad和viewDidAppear之间的差异

#2


4  

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.

我将把你介绍给苹果的文档,因为我认为有必要对视图控制器的生命周期做更多的解释,而不是仅仅回答你的问题。

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

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

Ultimately, your view controller has a life cycle:

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

init - however you initialize your view controller

初始化——不管你如何初始化你的视图控制器

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:补充那些:

viewDidDisappear: - complements viewDidAppear:

viewDidAppear viewDidDisappear:补充:

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];
    } 
}

#3


1  

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 viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of 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或那些,他们将被执行之前,用户可以看到视图——可能导致短冻结你的应用。它可能是好主意首先显示用户一个无人居住的视图与活动的指标。当您完成了您的网络,这可能需要一两秒钟(或者甚至可能失败——谁知道呢?),您可以使用您的数据填充视图。关于如何做到这一点,可以在各种twitter客户端看到很好的例子。例如,当您在Twitterrific中查看作者的详细页面时,视图只表示“加载”,直到网络查询完成。

ViewDidLoad calls only once when you initialized your ViewController but Viewdidapper calls every time.

ViewDidLoad只调用一次,当你初始化你的ViewController时,每次都是Viewdidapper调用。

#4


1  

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.

只有当主线程(UI线程)不繁忙时,activityindicatorview才会激活。viewDidLoad:和viewDidAppear:都在主线程上执行。如前所述,如果initializeArrays方法没有在单独的线程中执行,那么activityindicatorview将永远没有时间进行动画。

#5


1  

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.

调用(自我。activityIndicatorView startAnimating]基本上会“标记”activityIndicatorView,这样主线程上的另一个UI函数将启动它的动画。(这就是为什么主线程或“UI”线程是重要的,因为所有动画和对屏幕的视觉更新都是在这个线程上进行协调的)。所以要让activityIndicator启动的函数在initializearray完成并且你已经调用了stopAnimating之后才会被调用。

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];
}

#6


0  

View Did Load - First method , which is called when view is loaded first time but not appeared on screen/window, only loaded.

viewdidload - 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.

viewDidAppear之后——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(将被调用次数)

#1


215  

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.

请按照下面的视图控制器的生命周期。您将对应用程序的编码和性能感到惊讶。

ios7 - viewDidLoad和viewDidAppear之间的差异

#2


4  

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.

我将把你介绍给苹果的文档,因为我认为有必要对视图控制器的生命周期做更多的解释,而不是仅仅回答你的问题。

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

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

Ultimately, your view controller has a life cycle:

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

init - however you initialize your view controller

初始化——不管你如何初始化你的视图控制器

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:补充那些:

viewDidDisappear: - complements viewDidAppear:

viewDidAppear viewDidDisappear:补充:

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];
    } 
}

#3


1  

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 viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of 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或那些,他们将被执行之前,用户可以看到视图——可能导致短冻结你的应用。它可能是好主意首先显示用户一个无人居住的视图与活动的指标。当您完成了您的网络,这可能需要一两秒钟(或者甚至可能失败——谁知道呢?),您可以使用您的数据填充视图。关于如何做到这一点,可以在各种twitter客户端看到很好的例子。例如,当您在Twitterrific中查看作者的详细页面时,视图只表示“加载”,直到网络查询完成。

ViewDidLoad calls only once when you initialized your ViewController but Viewdidapper calls every time.

ViewDidLoad只调用一次,当你初始化你的ViewController时,每次都是Viewdidapper调用。

#4


1  

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.

只有当主线程(UI线程)不繁忙时,activityindicatorview才会激活。viewDidLoad:和viewDidAppear:都在主线程上执行。如前所述,如果initializeArrays方法没有在单独的线程中执行,那么activityindicatorview将永远没有时间进行动画。

#5


1  

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.

调用(自我。activityIndicatorView startAnimating]基本上会“标记”activityIndicatorView,这样主线程上的另一个UI函数将启动它的动画。(这就是为什么主线程或“UI”线程是重要的,因为所有动画和对屏幕的视觉更新都是在这个线程上进行协调的)。所以要让activityIndicator启动的函数在initializearray完成并且你已经调用了stopAnimating之后才会被调用。

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];
}

#6


0  

View Did Load - First method , which is called when view is loaded first time but not appeared on screen/window, only loaded.

viewdidload - 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.

viewDidAppear之后——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(将被调用次数)