UIViewController生命周期

  UIViewControl是IOS程序中的一个重要组成部分,扮演者一个大管家的身份,管理着程序中的众多视图,今天看看了官方文档并做了如下一些简单的记录:

何时加载view,加载的原则是什么,视图何时消失等问题,文档中讲的都很详细。

  Controller的view最好在需要显示时再去加载,并且在系统发出内存警告时释放比必要的view及相关的数据对象。

一、UIViewController的初始化

  初始化时会根据需要调用init,initWithCoder等相关函数,这个时候我们可以做一下简单的初始化操作,建立ViewController中需要使用的数据模型等,不建议在初始化阶段就直接创建view及其他与显示有关的对象(应该放到loadView的时候去创建,或者采用懒加载的方法创建)。

  我们都知道ViewController可以通过代码和xib两种方式创建,这两种方式的初始化流程也不尽相同。

  1)使用xib创建的VC

  xib其实最终是会把我们的设置保存成一个数据集,当需要初始化构建VC的时候,回去读取记录的数据集,然后帮我们动态的创建VC,因此可以想象它在初始化时会先去找看是否实现initWithCoder方法,如果该类实现了该方法,就直接调用initWithCoder方法创建对象,如果没有实现的话就调用init方法。调用完初始化方法以后紧接着会调用awakeFromNib方法,在这个方法里面我们可以做进一步的初始化操作。

  2)使用代码创建VC

  使用代码创建时,我们根据需要手动的创建VC中的数据,如果自己定制VC时,还需要在init中调用[super init]。

二、UIViewController中View的load和unload

  前面讲了不建议在VC初始化的时候就创建view及其他与显示相关的代码,官方文档建议将View的初始化操作放到loadView的时候再做,当VC接到内存告警时会调用didRecieveMemoryWarning这个时候我们就要做出响应,释放暂时不需要的对象。如果无视这个警告,系统内存不够用时会会继续发送,如果还得不到处理就会强制退出程序。下面看具体的loadView和unloadView时候都会做什么操作。

  1)Load周期

  当需要显示或者访问view属性时,view没有创建的话,VC就会调用loadView方法,在这个时候会创建一个view并将其赋给VC.view属性。紧接着就会调用VC的viewDidLoad方法,这个时候VC.view保证是有值的,可以做进一步的初始化操作,例如添加一些subview。注意:定制VC时,如果覆盖loadView方法,不需要调用[super loadView]方法。

  2)Unload周期

  当app收到内存警告的时候,会调用每一个VC的didRecieveMemoryWarning方法,我们需要做出响应,释放程序中暂时不需要的资源。通常都会重写该方法,重写时候需要调用super的该方法。如果检测到当前VC的view可以被安全释放的话,就会调用viewWillUnload方法,这个我们必须要重视,因为当VC的view消失时候它的subviews可能会被一起释放,我们需要根据具体情况做一些记录,以保证下次能够正确创建,同时不出现内存泄漏。调用viewWillUnload以后,会将VC.view属性设置成nil,然后在调用viewDidUnload方法,这个时候我们可以释放那些强引用的对象。

官方文档:The View Controller
Life Cycle

https://developer.apple.com/library/ios/samplecode/AdvancedTableViewCells/Introduction/Intro.html

View controllers are an essential part of managing your app’s resources. View controllers allow you to break your app up into multiple parts and instantiate only the parts that are needed. But more than that, a view controller itself
manages different resources and instantiates them at different times. For example, a view controller’s view hierarchy is instantiated only when the view is accessed; typically, this occurs only when the view is displayed on screen. If multiple view controllers
are pushed onto a navigation stack at the same time, only the topmost view controller’s contents are visible, which means only its views are accessed. Similarly, if a view controller is not presented by a navigation controller, it does not need to instantiate
its navigation item. By deferring most resource allocation until it is needed, view controllers use less resources.

When memory available to the app runs low, all view controllers are automatically notified by the system. This allows the view controller to purge caches and other objects that can be easily recreated later when memory is more plentiful. The exact behavior
varies depending on which version of iOS your app is running on, and this has implications for your view controller design.

Carefully managing the resources associated with your view controllers is critical to making your app run efficiently. You should also prefer lazy allocation; objects that are expensive to create or maintain should be allocated later and only when needed. For
this reason, your view controllers should separate objects needed throughout the lifetime of the view controller from objects that are only necessary some of the time. When your view controller receives a low-memory warning, it should be prepared to reduce
its memory usage if it is not visible onscreen.

Initializing a View Controller

When a view controller is first instantiated, it creates or loads objects it needs through its lifetime. It should not create its view hierarchy or objects associated with displaying content. It should focus
on data objects and objects needed to implement its critical behaviors.

Initializing a View Controller Loaded from a Storyboard

When you create a view controller in a storyboard, the attributes you configure in Interface Builder are serialized into an archive. Later, when the view controller is instantiated, this archive is loaded into
memory and processed. The result is a set of objects whose attributes match those you set in Interface Builder. The archive is loaded by calling the view controller’s initWithCoder: method.
Then, the awakeFromNib method
is called on any object that implements that method. You use this method to perform any configuration steps that require other objects to already be instantiated.

For more on archiving and archiving, see Archives
and Serializations Programming Guide
.

Initializing View Controllers Programmatically

If a view controller allocates its resources programmatically, create a custom initialization method that is specific to your view controller. This method should call the super class’s init method
and then perform any class specific initialization.

In general, do not write complex initialization methods. Instead, implement a simple initialization method and then provide properties for clients of your view controller to configure its behaviors.

A View Controller Instantiates Its View Hierarchy When Its View is Accessed

Whenever some part of your app asks the view controller for its view object and that object is not currently in memory, the view controller loads the view hierarchy into memory and stores it in its view property
for future reference. The steps that occur during the load cycle are:

  1. The view controller calls its loadView method.
    The default implementation of the loadView method does one of two things:

    • If the view controller is associated with a storyboard, it loads the views from the storyboard.

    • If the view controller is not associated with a storyboard, an empty UIView object
      is created and assigned to the view property.

  2. The view controller calls its viewDidLoad method,
    which enables your subclass to perform any additional load-time tasks.

Figure 4-1 shows a visual representation of the load cycle, including several of the
methods that are called. Your app can override both theloadView and the viewDidLoad methods
as needed to facilitate the behavior you want for your view controller. For example, if your app does not use storyboards but you want additional views to be added to the view hierarchy, you override the loadView method
to instantiate these views programatically.

Figure 4-1  Loading a view into memory

Loading a View Controller’s View from a Storyboard

Most view controllers load their view from an associated storyboard. The advantage of using storyboards is that they allow you to
lay out and configure your views graphically, making it easier and faster to adjust your layout. You can iterate quickly through different versions of your user interface to end up with a polished and refined design.

Creating the View in Interface Builder

Interface Builder is part of Xcode and provides an intuitive way to create and configure the views for your view controllers. Using Interface Builder, you assemble views and controls by manipulating them directly,
dragging them into the workspace, positioning them, sizing them, and modifying their attributes using an inspector window. The results are then saved in a storyboard file, which stores the collection of objects you assembled along with information about all
the customizations you made.

Configuring the View Display Attributes in Interface Builder

To help you layout the contents of your view properly, Interface Builder provides controls that let you specify whether the view has a navigation bar, a toolbar, or other objects that might affect the position
of your custom content. If the controller is connected to container controllers in the storyboard, it can infer these settings from the container, making it easier to see exactly how it should appear at runtime.

Configuring Actions and Outlets for Your View Controller

Using Interface Builder, you create connections between the views in your interface and your view controller.

Listing 4-1 shows the declaration of a custom MyViewController class’s
two custom outlets (designated by the IBOutlet keyword)
and a single action method (designated by the IBAction return
type). The declarations are made in a category inside the implementation file. The outlets store references to a button and a text field in the storyboard, while the action method responds to taps in the button.

Listing 4-1  Custom view controller class declaration

@interface MyViewController()
@property (nonatomic) IBOutlet id myButton;
@property (nonatomic) IBOutlet id myTextField;
 
- (IBAction)myAction:(id)sender;
@end

Figure 4-2 shows the connections you would create among the objects in such a MyViewController class.

Figure 4-2  Connections in the storyboard

When the previously configured MyViewController class is created and presented, the view controller infrastructure automatically
loads the views from the storyboard and reconfigures any outlets or actions. Thus, by the time the view is presented to the user, the outlets and actions of your view controller are set and ready to be used. This ability to bridge between your runtime code
and your design-time resource files is one of the things that makes storyboards so powerful.

Creating a View Programmatically

If you prefer to create views programmatically, instead of using a storyboard, you do so by overriding your view controller’s loadView method.
Your implementation of this method should do the following:

  1. Create a root view object.

    The root view contains all other views associated with your view controller. You typically define the frame for this view to match the size of the app window, which itself should fill the screen. However,
    the frame is adjusted based on how your view controller is displayed. See“Resizing
    the View Controller’s Views.”

    You can use a generic UIView object,
    a custom view you define, or any other view that can scale to fill the screen.

  2. Create additional subviews and add them to the root view.

    For each view, you should:

    1. Create and initialize the view.

    2. Add the view to a parent view using the addSubview: method.

  3. If you are using auto layout, assign sufficient constraints to each of the views you just created to control the position and size of your views. Otherwise, implement the viewWillLayoutSubviews and viewDidLayoutSubviews methods
    to adjust the frames of the subviews in the view hierarchy. See “Resizing
    the View Controller’s Views.”

  4. Assign the root view to the view property of
    your view controller.

Listing 4-2 shows an example implementation of the loadView method.
This method creates a pair of custom views in a view hierarchy and assigns them to the view controller.

Listing 4-2  Creating views programmatically

- (void)loadView
{
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
    UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];
    contentView.backgroundColor = [UIColor blackColor];
    self.view = contentView;
 
    levelView = [[LevelView alloc] initWithFrame:applicationFrame viewController:self];
    [self.view addSubview:levelView];
}

Note: When overriding the loadView method to create your views programmatically, you should
not call super. Doing so initiates the default view-loading behavior and usually just wastes CPU cycles. Your own implementation of the loadView method
should do all the work that is needed to create a root view and subviews for your view controller. For more information on the view loading process, see “A
View Controller Instantiates Its View Hierarchy When Its View is Accessed.”

Managing Memory Efficiently

When it comes to view controllers and memory management, there are two issues to consider:

  • How to allocate memory efficiently

  • When and how to release memory

Although some aspects of memory allocation are strictly yours to decide, the UIViewController class
provides some methods that usually have some connection to memory management tasks. Table 4-1 lists the places in your view controller
object where you are likely to allocate or deallocate memory, along with information about what you should be doing in each place.

Table 4-1  Places to allocate and deallocate memory

Task

Methods

Discussion

Allocating critical data structures required by your view controller

Initialization methods

Your custom initialization method (whether it is named init or something else) is always responsible
for putting your view controller object in a known good state. This includes allocating whatever data structures are needed to ensure proper operation.

Creating your view objects

loadView

Overriding the loadView method is required only if you intend to create your views programmatically. If you are using storyboards, the views are loaded automatically from the
storyboard file.

Creating custom objects

Custom properties and methods

Although you are free to use other designs, consider using a pattern similar theloadView method.
Create a property that holds the object and a matched method to initialize it. When the property is read and its value is nil, call the associated load method.

Allocating or loading data to be displayed in your view

viewDidLoad

Data objects are typically provided by configuring your view controller’s properties. Any additional data objects your view controller wants to create should be done by overriding the viewDidLoad method.
By the time this method is called, your view objects are guaranteed to exist and to be in a known good state.

Responding to low-memory notifications

didReceiveMemoryWarning

Use this method to deallocate all noncritical objects associated with your view controller. On iOS 6, you can also use this method to release references to view objects.

Releasing critical data structures required by your view controller

dealloc

Override this method only to perform any last-minute cleanup of your view controller class. Objects stored in instance variables and properties are automatically released; you do not need to release them explicitly.

On iOS 6 and Later, a View Controller Unloads Its Own Views When Desired

The default behavior for a view controller is to load its view hierarchy when the view property
is first accessed and thereafter keep it in memory until the view controller is disposed of. The memory used by a view to draw itself onscreen is potentially quite large. However, the system automatically releases these expensive resources when the view is
not attached to a window. The remaining memory used by most views is small enough that it is not worth it for the system to automatically purge and recreate the view hierarchy.

You can explicitly release the view hierarchy if that additional memory is necessary for your app. Listing
4-3 overrides thedidReceiveMemoryWarning method
to accomplish this. First, is calls the superclass’s implementation to get any required default behavior. Then, it cleans up the view controller’s resources. Finally, it tests to see if the view controller’s view is not onscreen. If the view is associated
with a window, then it cleans up any of the view controller’s strong references to the view and its subviews. If the views stored data that needs to be recreated, the implementation of this method should save that data before releasing any of the references
to those views.

Listing 4-3  Releasing the views of a view controller not visible on screen

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Add code to clean up any of your own resources that are no longer necessary.
    if ([self.view window] == nil)
    {
        // Add code to preserve data stored in the views that might be
        // needed later.
 
        // Add code to clean up other strong references to the view in
        // the view hierarchy.
        self.view = nil;
    }

The next time the view property
is accessed, the view is reloaded exactly as it was the first time.

On iOS 5 and Earlier, the System May Unload Views When Memory Is Low

In earlier versions of iOS, the system automatically attempts to unload a view controller’s views when memory is low. The steps that occur during the unload cycle are as follows:

  1. The app receives a low-memory warning from the system.

  2. Each view controller calls its didReceiveMemoryWarning method.
    If you override this method, you should use it to release any memory or objects that your view controller object no longer needs. You must call super at some point in your
    implementation to ensure that the default implementation runs. On iOS 5 and earlier, the default implementation attempts to release the view. On iOS 6 and later, the default implementation exits.

  3. If the view cannot be safely released (for example, it is visible onscreen), the default implementation exits.

  4. The view controller calls its viewWillUnload method.
    A subclass typically overrides this method when it needs to save any view properties before the views are destroyed.

  5. It sets its view property
    to nil.

  6. The view controller calls its viewDidUnload method.
    A subclass typically overrides this method to release any strong references it has to those views.

Figure 4-3 shows a visual representation of the unload cycle for a view controller.

Figure 4-3  Unloading a view from
memory

Resource Management in View Controllers的更多相关文章

  1. 【IOS笔记】Resource Management in View Controllers

    Resource Management in View Controllers 视图控制器的资源管理 View controllers are an essential part of managin ...

  2. View Controller Programming Guide for iOS---(五)---Resource Management in View Controllers

    Resource Management in View Controllers View controllers are an essential part of managing your app’ ...

  3. 【IOS笔记】Creating Custom Content View Controllers

    Creating Custom Content View Controllers 自定义内容视图控制器 Custom content view controllers are the heart of ...

  4. View Controller Programming Guide for iOS---(四)---Creating Custom Content View Controllers

    Creating Custom Content View Controllers 创建自定义内容视图控制器 Custom content view controllers are the heart ...

  5. iphone dev 入门实例2:Pass Data Between View Controllers using segue

    Assigning View Controller Class In the first tutorial, we simply create a view controller that serve ...

  6. The Role of View Controllers

    https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/index.html# ...

  7. Presenting view controllers on detached view controllers is discouraged <CallViewController: 0x14676e240>.

    今天在优化app时,发现程序出现这种警告:“ Presenting view controllers on detached view controllers is discouraged <C ...

  8. 更轻量的 View Controllers

    iew controllers 通常是 iOS 项目中最大的文件,并且它们包含了许多不必要的代码.所以 View controllers 中的代码几乎总是复用率最低的.我们将会看到给 view con ...

  9. 【IOS笔记】Using View Controllers in Your App

    参考:http://www.cnblogs.com/patientAndPersist/p/3279645.html Using View Controllers in Your App Whethe ...

随机推荐

  1. Java中"str1.equals(str2)"和"str1==str2"的区别

    大家好,这是我的第一篇博客,作为即将入职的学生,我现在的心情是既好奇又兴奋,对未知的职场生活充满了无限的憧憬,也想赶紧对大学生活say goodbye,因为自己的能力现在还比较有限,我想通过博客这个平 ...

  2. ssh实现免密码登录和文件传输

    一般的用户名密码认证不安全,很容易被暴力破解,还不方便:而大多数人都是选择使用 SSH 密钥认证,不仅安全还不用每次输密码 ssh密钥对 # 使用 ssh-keygen 生成非对称密钥,一路回车即可 ...

  3. dl, dt, dd /line-height /loat /vertical-align 问题

    刚刚在看张鑫旭大神的个人网站,看到一篇关于“css瓶颈”的深度好文,地址为:http://www.zhangxinxu.com/wordpress/?p=2523 关于张大神在文章里面提到的四个问题: ...

  4. LuceneNet 搜索一

    1.引用读取PDF文件组件 FontBox-0.1.0-dev.dll IKVM.GNU.Classpath.dll IKVM.Runtime.dll PDFBox-0.7.3.dll 2.添加off ...

  5. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  6. 移动端页面输入法挡住input输入框的解决方法

    1,宽高用了百分比或者vw/vh布局的,input输入框的最外层父容器的可用JS动态设置为当前窗口的宽高(防止输入法的弹出令页面变形) 2,最外层父容器用了fixed定位的,不要用top:0;要用bo ...

  7. 正则中使用ASCII码,取值范围

    [^\x00-\xFF]  : 表示匹配Ascii码大于255的那些字符 基于浏览器的工具: https://regexr.com/

  8. hdu 2586 (lca-RMQ)

    #include <iostream> #include <cstdlib> #include <cstring> #include <queue> # ...

  9. 关于python的元组操作

    关于元组: 元组和列表是类似的,但是元组中的数据是不可以修改的. 元组是一对 () 元组操作: 元组是不可以修改的所以对元组的操作极少 定义空元组(因为元组一旦创建,数据不可被修改,所以极少创建空元组 ...

  10. Python爬虫之selenium库使用详解

    Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...