想了解 iOS UIViewController 生命周期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5562938/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:29:06  来源:igfitidea点击:

Looking to understand the iOS UIViewController lifecycle

iosuiviewcontrollerxamarin.ioslifecycle

提问by Lorenzo B

Could you explain me the correct manner to manage the UIViewControllerlifecycle?

你能解释一下管理UIViewController生命周期的正确方式吗?

In particular, I would like to know how to use Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloadand Disposemethods in Mono Touch for a UIViewControllerclass.

我特别想知道如何使用InitializeViewDidLoadViewWillAppearViewDidAppearViewWillDisappearViewDidDisappearViewDidUnloadDispose在单触摸方法一UIViewController类。

回答by Jacob Knobel

All these commands are called automatically at the appropriate times by iOS when you load/present/hide the view controller. It's important to note that these methods are attached to UIViewControllerand not to UIViews themselves. You won't get any of these features just using a UIView.

当您加载/呈现/隐藏视图控制器时,iOS 会在适当的时间自动调用所有这些命令。重要的是要注意这些方法是附加UIViewControllerUIViews 本身而不是附加到s 本身。仅使用UIView.

There's great documentation on Apple's site here. Putting in simply though:

Apple 网站上有很棒的文档here。简单地说:

  • ViewDidLoad- Called when you create the class and load from xib. Great for initial setup and one-time-only work.

  • ViewWillAppear- Called right before your view appears, good for hiding/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.

  • ViewDidAppear- Called after the view appears - great place to start an animations or the loading of external data from an API.

  • ViewWillDisappear/DidDisappear- Same idea as ViewWillAppear/ViewDidAppear.

  • ViewDidUnload/ViewDidDispose- In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here.

  • ViewDidLoad- 在创建类并从 xib 加载时调用。非常适合初始设置和一次性工作。

  • ViewWillAppear- 在您的视图出现之前调用,适用于隐藏/显示字段或您希望每次在视图可见之前发生的任何操作。因为您可能会在视图之间来回切换,所以每次您的视图即将出现在屏幕上时都会调用它。

  • ViewDidAppear- 在视图出现后调用 - 开始动画或从 API 加载外部数据的好地方。

  • ViewWillDisappear/ DidDisappear-相同的思路ViewWillAppear/ ViewDidAppear

  • ViewDidUnload/ ViewDidDispose- 在 Objective-C 中,这是您进行清理和发布内容的地方,但这是自动处理的,因此您在这里真正需要做的并不多。

回答by Haider

UPDATE: ViewDidUnload was deprecated in iOS 6, so updated the answer accordingly.

更新: ViewDidUnload 在 iOS 6 中已被弃用,因此相应地更新了答案。

The UIViewController lifecycle is diagrammed here:

UIViewController 生命周期如下图所示:

A view controller's lifecycle, diagrammed

视图控制器的生命周期,图解

The advantage of using Xamarin Native/Mono Touch, is that it uses the native APIs, and so it follows the same ViewController lifecycle as you would find in Apple's Documentation.

使用 Xamarin Native/Mono Touch 的优势在于它使用本机 API,因此它遵循与 Apple 文档中相同的 ViewController 生命周期。

回答by onCompletion

This is for latest iOS Versions(Modified with Xcode 9.3, Swift 4.1). Below are all the stages which makes the lifecycle of a UIViewControllercomplete.

这是针对最新的 iOS 版本(使用Xcode 9.3、Swift 4.1修改)。以下是使生命周期UIViewController完整的所有阶段。

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Let me explain all those stages.

让我解释所有这些阶段。

1. loadView

1. loadView

This event creates/loads the view that the controller manages. It can load from an associated nib file or an empty UIViewif null was found. This makes it a good place to create your views in code programmatically.

此事件创建/加载控制器管理的视图。它可以从关联的 nib 文件中加载,UIView如果找到 null,则可以从空文件中加载。这使它成为以编程方式在代码中创建视图的好地方。

This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly. Only override this method when you programmatically create views and assign the root view to the viewproperty Don't call super method when you override loadView

如果子类不使用笔尖,子类应该在这里创建它们的自定义视图层次结构。永远不应该直接调用。仅当您以编程方式创建视图并将根视图分配给view属性时才覆盖此方法覆盖loadView时不要调用超级方法

2. loadViewIfNeeded

2. loadViewIfNeeded

If incase the view of current viewControllerhas not been set yet then this method will load the view but remember, this is only available in iOS >=9.0. So if you are supporting iOS <9.0 then don't expect it to come into the picture.

如果当前视图viewController尚未设置,则此方法将加载视图,但请记住,这仅在 iOS >=9.0 中可用。因此,如果您支持 iOS <9.0,则不要指望它会出现。

Loads the view controller's view if it has not already been set.

如果尚未设置,则加载视图控制器的视图。

3. viewDidLoad

3. viewDidLoad

The viewDidLoadevent is only called when the view is created and loaded into memory but the bounds for the view are not defined yet. This is a good place to initialise the objects that the view controller is going to use.

viewDidLoad事件仅在创建视图并将其加载到内存中时调用,但尚未定义视图的边界。这是初始化视图控制器将要使用的对象的好地方。

Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

在加载视图后调用。对于在代码中创建的视图控制器,这是在 -loadView 之后。对于从笔尖未归档的视图控制器,这是在设置视图之后。

4. viewWillAppear

4. viewWillAppear

This event notifies the viewControllerwhenever the view appears on the screen. In this step the view has bounds that are defined but the orientation is not set.

viewController每当视图出现在屏幕上时,此事件都会通知。在此步骤中,视图具有定义的边界,但未设置方向。

Called when the view is about to made visible. Default does nothing.

当视图即将可见时调用。默认什么都不做。

5. viewWillLayoutSubviews

5. viewWillLayoutSubviews

This is the first step in the lifecycle where the bounds are finalised. If you are not using constraints or Auto Layout you probably want to update the subviews here. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.

这是最终确定边界的生命周期的第一步。如果您不使用约束或自动布局,您可能希望在此处更新子视图。这仅在 iOS >=5.0 中可用。因此,如果您支持 iOS <5.0,则不要指望它会出现。

Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop.

在调用视图控制器视图的 layoutSubviews 方法之前调用。子类可以根据需要实现。默认值为 nop。

6. viewDidLayoutSubviews

6. viewDidLayoutSubviews

This event notifies the view controller that the subviews have been setup. It is a good place to make any changes to the subviews after they have been set. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.

此事件通知视图控制器已设置子视图。这是在设置子视图后对其进行任何更改的好地方。这仅在 iOS >=5.0 中可用。因此,如果您支持 iOS <5.0,则不要指望它会出现。

Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop.

在调用视图控制器视图的 layoutSubviews 方法后立即调用。子类可以根据需要实现。默认值为 nop。

7. viewDidAppear

7. viewDidAppear

The viewDidAppearevent fires after the view is presented on the screen. Which makes it a good place to get data from a backend service or database.

viewDidAppear事件在视图显示在屏幕上后触发。这使它成为从后端服务或数据库获取数据的好地方。

Called when the view has been fully transitioned onto the screen. Default does nothing

当视图完全转换到屏幕上时调用。默认什么都不做

8. viewWillDisappear

8. viewWillDisappear

The viewWillDisappearevent fires when the view of presented viewControlleris about to disappear, dismiss, cover or hide behind other viewController. This is a good place where you can restrict your network calls, invalidate timer or release objects which is bound to that viewController.

viewWillDisappear事件触发时的呈现的视图viewController是即将消失,解除,盖或隐藏另一个后面viewController。这是一个很好的地方,您可以在其中限制您的网络调用、使计时器无效或释放绑定到它的对象viewController

Called when the view is dismissed, covered or otherwise hidden.

当视图被关闭、覆盖或以其他方式隐藏时调用。

9. viewDidDisappear

9. viewDidDisappear

This is the last step of the lifecycle that anyone can address as this event fires just after the view of presented viewControllerhas been disappeared, dismissed, covered or hidden.

这是任何人都可以解决的生命周期的最后一步,因为此事件会在呈现的视图viewController消失、关闭、覆盖或隐藏后立即触发。

Called after the view was dismissed, covered or otherwise hidden. Default does nothing

在视图被关闭、覆盖或以其他方式隐藏后调用。默认什么都不做

Now as per Applewhen you are implementing this methods you should remember to call superimplementation of that specific method.

现在按照Apple,当您实现此方法时,您应该记住调用super该特定方法的实现。

If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.) In the specified NIB, the File's Owner proxy should have its class set to your view controller subclass, with the view outlet connected to the main view. If you invoke this method with a nil nib name, then this class' -loadViewmethod will attempt to load a NIB whose name is the same as your view controller's class. If no such NIB in fact exists then you must either call -setView:before -viewis invoked, or override the -loadViewmethod to set up your views programatically.

如果你继承 UIViewController,你必须调用这个方法的超级实现,即使你没有使用 NIB。(为方便起见,默认的init方法会为你做这个,并指定零供双方的这种方法的参数。)在指定的NIB,文件拥有者代理应该有它的类集合到您的视图控制器子类,这样的观点出口连接到主视图。如果您使用 nil 笔尖名称调用此方法,则该类的-loadView方法将尝试加载名称与您的视图控制器类相同的笔尖。如果实际上不存在这样的 NIB,那么您必须-setView:-view被调用之前调用,或者覆盖该-loadView方法以编程方式设置您的视图。

Hope this helped. Thanks.

希望这有帮助。谢谢。

UPDATE- As @ThomasW pointed inside comment viewWillLayoutSubviewsand viewDidLayoutSubviewswill also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.

更新- 正如@ThomasW 在注释中指出的那样,viewWillLayoutSubviews并且viewDidLayoutSubviews在加载主视图的子视图时也会在其他时间调用,例如加载表视图或集合视图的单元格时。

UPDATE- As @Maria pointed inside comment, description of loadViewwas updated

更新- 正如@Maria 在评论中指出的那样,描述loadView已更新

回答by Rajamohan S

iOS 10,11(Swift 3.1,Swift 4.0)

iOS 10,11 (Swift 3.1,Swift 4.0)

According to UIViewControllerin UIKitdevelopers,

UIViewControllerUIKit开发商,

1. loadView()

1.加载视图()

This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

如果子类不使用nib,子类应该在这里创建它们的自定义视图层次结构。永远不应该直接调用。

2. loadViewIfNeeded()

2.loadViewIfNeeded()

Loads the view controller's view if it has not already been set.

如果尚未设置,则加载视图控制器的视图。

3. viewDidLoad()

3.viewDidLoad()

Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

在加载视图后调用。对于在代码中创建的视图控制器,这是在 -loadView 之后。对于从笔尖未归档的视图控制器,这是在设置视图之后。

4. viewWillAppear(_ animated: Bool)

4. viewWillAppear(_ 动画: Bool)

Called when the view is about to made visible. Default does nothing

当视图即将可见时调用。默认什么都不做

5. viewWillLayoutSubviews()

5. viewWillLayoutSubviews()

Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.

在调用视图控制器视图的 layoutSubviews 方法之前调用。子类可以根据需要实现。默认什么都不做。

6. viewDidLayoutSubviews()

6. viewDidLayoutSubviews()

Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.

在调用视图控制器视图的 layoutSubviews 方法后立即调用。子类可以根据需要实现。默认什么都不做。

7. viewDidAppear(_ animated: Bool)

7. viewDidAppear(_ 动画: Bool)

Called when the view has been fully transitioned onto the screen. Default does nothing

当视图完全转换到屏幕上时调用。默认什么都不做

8. viewWillDisappear(_ animated: Bool)

8. viewWillDisappear(_ 动画: Bool)

Called when the view is dismissed, covered or otherwise hidden. Default does nothing

当视图被关闭、覆盖或以其他方式隐藏时调用。默认什么都不做

9. viewDidDisappear(_ animated: Bool)

9. viewDidDisappear(_动画:BOOL

Called after the view was dismissed, covered or otherwise hidden. Default does nothing

在视图被关闭、覆盖或以其他方式隐藏后调用。默认什么都不做

10. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

10. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

Called when the view is Transitioning.

当视图正在转换时调用。

11. willMove(toParentViewController parent: UIViewController?)

11. willMove(toParentViewController parent: UIViewController?)

12. didMove(toParentViewController parent: UIViewController?)

12. didMove(toParentViewController parent: UIViewController?)

These two methods are public for container subclasses to call when transitioning between child controllers. If they are overridden, the overrides should ensure to call the super.

这两个方法是公共的,供容器子类在子控制器之间转换时调用。如果他们被覆盖,覆盖的应该确保调用父类。

The parent argument in both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new parent view controller.

当子项从其父项中删除时,这两种方法中的 parent 参数都为零;否则它等于新的父视图控制器。

13. didReceiveMemoryWarning()

13. didReceiveMemoryWarning()

Called when the parent application receives a memory warning. On iOS 6.0 it will no longer clear the view by default.

当父应用程序收到内存警告时调用。在 iOS 6.0 上,默认情况下将不再清除视图。

回答by Saad

As of iOS 6 and onward. The new diagram is as follows:

从 iOS 6 开始。新图如下:

enter image description here

在此处输入图片说明

回答by Alexey Pelekh

Let's concentrate on methods, which are responsible for the UIViewController'slifecycle:

让我们专注于方法,它们负责UIViewController 的生命周期:

  • Creation:

    - (void)init

    - (void)initWithNibName:

  • View creation:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Handling of view state changing:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Memory warning handling:

    - (void)didReceiveMemoryWarning

  • Deallocation

    - (void)viewDidUnload

    - (void)dealloc

  • 创建:

    - (void)init

    - (void)initWithNibName:

  • 查看创建:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • 处理视图状态改变:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • 内存警告处理:

    - (void)didReceiveMemoryWarning

  • 解除分配

    - (void)viewDidUnload

    - (void)dealloc

UIViewController's lifecycle diagram

UIViewController 的生命周期图

For more information please take a look on UIViewController Class Reference.

有关更多信息,请查看UIViewController 类参考

回答by gjgjgj

The methods viewWillLayoutSubviewsand viewDidLayoutSubviewsaren't mentioned in the diagrams, but these are called between viewWillAppearand viewDidAppear. They can be called multiple times.

方法viewWillLayoutSubviewsviewDidLayoutSubviews未在图中提及,但它们在viewWillAppear和之间调用viewDidAppear。它们可以被多次调用。

回答by bobics

There's a lot of outdated and incomplete information here. For iOS 6 and neweronly:

这里有很多过时和不完整的信息。仅适用于iOS 6 及更新版本

  1. loadView[a]
  2. viewDidLoad[a]
  3. viewWillAppear
  4. viewWillLayoutSubviewsis the first time bounds are finalized
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. *viewWillLayoutSubviews[b]
  8. *viewDidLayoutSubviews[b]
  1. loadView[一种]
  2. viewDidLoad[一种]
  3. viewWillAppear
  4. viewWillLayoutSubviews是第一次确定边界
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. *viewWillLayoutSubviews[乙]
  8. *viewDidLayoutSubviews[乙]


Footnotes:

脚注:

(a) - If you manually nil out your view during didReceiveMemoryWarning, loadViewand viewDidLoadwill be called again. That is, by default loadViewand viewDidLoadonly gets called once per view controller instance.

(一) -如果你手动零出在你的看法didReceiveMemoryWarningloadViewviewDidLoad会被再次调用。也就是说,默认情况下loadViewviewDidLoad每个视图控制器实例只调用一次。

(b) May be called an additional 0or more times.

(b) 可以额外调用0次或更多次。

回答by Matt Becker

Haider's answer is correct for pre-iOS 6. However, as of iOS 6 viewDidUnload and viewWillUnload are never called. The docsstate: "Views are no longer purged under low-memory conditions and so this method is never called."

海德尔的答案是对前期的iOS 6,但是正确的,因为iOS 6的viewDidUnload和viewWillUnload的永远不会被调用。该文档的状态:“视图不再低内存情况下,因此这种方法不会被调用清除。”

回答by Luismi

Explaining State Transitions in the official doc: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html

在官方文档中解释状态转换:https: //developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html

This image shows the valid state transitions between various view ‘will' and ‘did' callback methods

此图显示了各种视图“will”和“did”回调方法之间的有效状态转换

Valid State Transitions:

有效的状态转换:


Taken from: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png


取自:https: //developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png