-viewWillAppear:和-viewDidAppear:有什么区别?


131

-[UIViewController viewWillAppear:]和之间有什么区别-[UIViewController viewDidAppear:]


1
感谢BoltClock,但请给我两个例子如果可能的话..
PJR

3
@BoltClock,如果那是真的,那会很好。我猜谁upvoted阅读方法名,但从未实际测量它15人......来到这里,从谷歌,因为这是不是他们之间的区别
亚当

1
具体来说:parentView.viewDidAppear在苹果实际显示parentView之前被称为很长时间... Apple首先(原子上)绘制所有子视图...如果您有很多子视图或复杂的子视图,那么“ viewDidAppear”可以称为tens或太快几百毫秒:(
亚当

Answers:


292

总的来说,这就是我要做的:

1)ViewDidLoad-每当我向视图添加控件时,应立即将其与该视图一起显示,然后将其放在ViewDidLoad方法中。基本上,只要将视图加载到内存中,就会调用此方法。因此,例如,如果我的视图是带有3个标签的表单,则可以在此处添加标签;没有这些形式,视图将永远不存在。

2)ViewWillAppear:我通常使用ViewWillAppear只是为了更新表单上的数据。因此,对于上面的示例,我将使用它来将域中的数据实际加载到表单中。创建UIView相当昂贵,您应该避免在ViewWillAppear方法上执行尽可能多的操作,因为调用该方法时,它意味着iPhone已经准备好向用户显示UIView,而您在此处所做的任何繁重的工作将以非常明显的方式影响性能(例如动画被延迟等)。

3)ViewDidAppear:最后,我使用ViewDidAppear为需要很长时间才能执行的事情启动新线程,例如进行webservice调用以获取上述表单的额外数据,这是因为视图已经存在并正在显示给用户,则可以在获取数据时向用户显示一个漂亮的“等待”消息。


4
抱歉,但是“将数据从我的域加载到表单中”是viewWillAppear什么意思?您是说要通过网络下载?但是,您还建议下载内容viewDidAppear吗?
Philip007

1
@ Philip007我认为Stack指的是这种类型的域:en.wikipedia.org/wiki/Domain-specific_modeling。数据是从模型或类似模型加载的。
dentarg

2
这个答案应该在文档中。弄清这三种方法之间的区别确实很有帮助。谢谢!
GangstaGraham 2013年

1
+1我有点困惑,无法理解这三个之间的区别,但是您刚刚将其清除得更加完美@ChetanBhalara
Chisx 2014年

@ChetanBhalara,但是如果您花很长时间ViewDidAppear进行操作,很容易使用户对UI
感到

46

viewDidLoad === >>>将您的初始化代码放在这里。不要放置在视图生命周期中可能会更改的动态数据。因此,如果您要从核心数据中提取数据,则在此视图的生命周期内这种情况可能会发生变化时,您不想在此处进行操作。例如:说您有一个选项卡控制器。您从tab1切换到tab2,并在tab2中的模型上进行了更改。如果返回tab1并且您的模型代码在viewDidLoad中完成,则不会更新(假设您未使用KVO或NSFetchedResultsController等)。

viewWillAppear === >>>每当视图即将出现时,无论视图是否已在内存中,都会调用此方法。将您的动态代码放在这里,例如模型逻辑。

viewDidAppear === >>>仅在确定视图在屏幕上(例如网络调用)时,才需要执行昂贵的操作。

注意:如果您的应用程序是后台运行并返回到前台,则需要使用NSNotificationCenter进行处理。我在下面的注释中为此编写了代码。您可能认为viewWillAppear / viewDidAppear将触发。在此处放置一个断点并对其进行测试。它不会开火。因此,如果您的应用在后台运行时发生了变化,则需要使用通知进行更新。


1
每次使应用程序最小化时,ViewWill或ViewDid是否会运行?
Jeef

2
@杰夫这是一个很好的问题。除非应用程序在后台被系统或用户杀死,否则它们都不会运行。要在未最小化的应用程序中获得通知,您必须使用NSNotificationCenter和addObserver作为名称UIApplicationWillEnterForegroundNotification。选择器应为applicationWillEnterForeground:它具有NSNotification参数。将您的代码放入该方法中以重新加载数据等。您可以做的是创建一个重新加载方法,您可以从该方法中调用该方法,如果需要保持一致,还可以使用viewDidAppear。
smileBot 2014年

2
@Jeef像这样:-(void)viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver:self选择器:@selector(applicationWillEnterForeground :)名称:UIApplicationWillEnterForegroundNotification object:nil]; }-(无效)applicationWillEnterForeground:(NSNotification *)notif {//用任何方式在此处回复}
smileBot 2014年

12

viewWillAppear在加载实际视图之前将调用该方法。

viewDidAppear当视图已经加载并且想要显示某些内容时,将调用该方法。


9

viewWillAppear:
■在将视图添加到窗口的视图层次结构之前调用
之前调用■在[vc.view layoutSubviews]之前调用(如有必要)
viewDidAppear
■在将视图添加到视图层次结构
之后调用■在[vc.view layoutSubviews]之后调用(如有必要)


7

一些观察:

  • viewDidLoad首次实例化视图时调用该方法。IBOutlet引用是在调用它之前被连接的,而不是在此之前。但是frame,视图的调用可能尚未建立。这是添加/配置子视图及其关联约束的好地方。但是,如果您要frame根据主视图的尺寸进行任何手动的值配置,则这些框架的配置应推迟到viewWillAppearviewDidLayoutSubviews

  • viewWillAppear当视图层次结构中的视图呈现即将开始时,将调用该方法。值得注意的是,这是在视图呈现的动画(如果有)的开始处调用的。viewWillDisappear当离开此视图的过渡开始时,显然会调用它的同伴。

  • viewDidAppear当完成视图的呈现时,尤其是在完成所有关联的动画之后,将调用此方法。viewDidDisappear当完成离开此视图的转换时,显然会调用它的同伴。

两个重要的警告:

  • viewDidLoad首次实例化视图时,仅调用一次,并且仅调用一次。另一方面,不仅会在首次显示视图时调用,viewWillAppear而且viewDidAppear还会在以后的每一次重新显示所讨论的相同视图时调用。例如,当您首次显示视图时,将同时调用这三种方法。如果有问题的观点随后呈现随后被解雇时,另一种观点认为viewWillAppear,并viewDidAppear在有问题的视图添加和动画回视图层次一般会被再次调用,但viewDidLoad不会。viewDidLoad仅在首次创建此特定实例时调用。

    因此,如果您希望每次重新显示视图时都执行某项操作(例如,关闭或弹出视图),请在viewWillAppear或中进行操作viewDidAppear。如果希望仅在首次实例化视图时才发生,请在中进行viewDidLoad

  • 的调用viewWillAppear并不保证将完全完成向该视图的转换。值得注意的是,如果您使用的是由实时用户输入驱动的交互式转换,但是可以取消该交互式转换。即,仅因为viewWillAppear被调用,并不意味着viewDidAppear将被调用。通常是这样,但是如果取消了交互式手势,则不会(因为过渡从未完成)。

    在WWDC 2013上,在交互式过渡的上下文中,演示者开玩笑说应将其重命名viewWillAppear为“ viewMightAppearviewWillProbablyAppeariReallyWishThisViewWouldAppear”。

    内置交互式手势的一个示例是当UINavigationController您使用时,您“从左边缘滑动”以启动视图弹出。该viewWillAppear会呼吁给你如雨后春笋般冒出的观点,但如果取消,“从左侧边缘滑动”,以返回到从中启动此弹出的姿态来看,在弹出被取消,viewDidAppear该视图你开始弹出到永远不会被调用。

    这样做的最终结果是,您应注意不要编写假定每个viewWillAppear最终都会调用的代码viewDidAppear。如果取消过渡,则情况并非如此。


5

viewwillappear将在加载视图之前调用,以便您可以在加载该视图之前执行某些任务,并且viewdidappear将在加载该视图之后调用,因此发布任务将在该方法中完成


4

“ will”和“ did”之间的区别...顾名思义,viewWillAppear在视图即将出现之前被调用,而viewDidAppear在视图确实出现时被调用。


查看接受的答案兄弟,其中包含70多个投票。:)
PJR

4

1)ViewWillAppear:该视图实际上已加载到内存中,在视图控制器中被调用一次并具有其框架,但仍未向用户显示

2)ViewDidAppear:控制器已添加到视图层次结构中,因此您可以将其呈现给下一个控制器,并且该视图确实布局了子视图




1

顾名思义,viewWillAppear在视图即将出现之前调用,在视图出现viewDidAppear时调用。


0

用例,即我什么时候应该使用哪个?

viewDidLoad -当标签,按钮(即任何控件/子视图)连接到视图的界面文件时,并且如果您想同时加载所有这些视图和ViewController的视图,以及是否要将其一次加载到内存中并完成了

viewWillAppear-例如,您希望每次viewController出现在屏幕上时更改视图的背景颜色。或者更现实的是,如果您想在白天的晚上使用DarkMode背景色,并在白天使用背景视图的浅色,请在viewWillAppear

另一个很好的用例在这里 https://stackoverflow.com/a/39395865/5438240

还要注意,如果您使用的是Navigation stack(UINavigationController),则将要弹出的viewController被viewWillDisappear()调用,而接下来将位于堆栈顶部的ViewController将被viewWillAppear()调用

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.