翻译苹果官网的文章一则
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html
初始化 ViewController
第一次实例化的时候,通过生命周期创建或者加载对象,它不应该创建view hierarchy 或者其他跟显示画面相关的内容,它应该关注对象,关注实现生命周期中特殊行为的对象。
初始化storyboard中加载的ViewController
当我们在storyboard中创建view controller时,配置的属性都会存储到一个配置信息文档中,之后当实例化时,文档就会被加载到内存和进程中去,结果就是会有一系列的符合之前配置信息的对象会生成,配置信息文档会被view controller的initwithcode:方法加载。这之后任何实现了awakeFromNib方法的对象调用这个方法。用这个方法配置信息。
用代码初始化ViewController
如果view controller用代码创建的,那么我们重写一下init方法,当然这个方法首先要调用父类的init方法,然后再加上自己的其他客户化的内容。
通常,实例化方法里面不要写过于复杂的方法,而是应该实现简单的功能,并且提供必要的属性给view controller的委托类从而配置它的行为。
ViewController 当访问VIEW属性时会实例化它的VIEW Hierarchy。
无论何时当你的app需要访问view,而view对象不在内存中时,view controller都会加载view hierarchy
进内存,并且存储在它的view属性内,循环加载的步骤如下:
1、view controller 调用自己的loadview方法。方法默认会实现下面的某一个内容:
* 如果view controller关联了一个storyboard,那么就从storyboard中加载。
* 如果没有关联的故事模板,那么会创建一个空的UIView对象,并且赋值给view属性。
2、view controller调用viewDidLoad方法,这能够确保你的子类能够执行额外的load-time任务。
下面的图示展示了view controller是如何循环加载的,包含了一些需要调用的方法。我们的app可以覆盖loadview方法和viewDidLoad方法。举个例子,如果你的app没有用storyboard,但是你却想增加一个view,这时可以覆盖loadview方法用代码初始化view。
下面这个图的标题是:向内存中加载view
从storyboard中加载一个view
大多数的view controller 从storyboard中加载他们的view,优点就是可以用可见的方式配置布局,这很容易也很快速。
在interface builder中创建view
interface builder是xcode的一部分,他可以给我们的viewcontroller提供方便的直观的方式去配置view的相关属性。在这里可以同时操控view和controller,控件直接拽到工作空间中,设置大小,属性等,设置完毕后直接存储在storyboard文件中。
在interface builder中配置view的图形属性
为了正确的展示内容布局,interface builder提供了控件可以让你去指定是否view有导航bar、工具bar等其他的对象,这些对象都可以影响你的定制内容。如果controller连接到容器中,也可以提供精确的运行时的显示效果。
为view controller配置Action和Outlet
利用IB,可以在view和controller之间建立连接。
下面的代码显示如何声明一个MyVIewController类的controller以及它的两个custom outlet 和一个 ibaciton方法。这个声明其实是在.m文件内的category。outlets存储了一个按钮和一个textfield引用。下面的方法则监听按钮的按下动作。
@interface MyViewController()
|
@property (nonatomic) IBOutlet id myButton;
|
@property (nonatomic) IBOutlet id myTextField;
|
|
- (IBAction)myAction:(id)sender;
|
@end |
而下面的图示则展示了上面代码部分建立的对象之间的连接
接下来介绍一下代码的方式创建视图(view)//1️⃣
如果你更喜欢用代码来创建视图,应该覆盖你的view controller 的loadview方法,你的方法实现应该遵从以下的几点:
1、创建一个根视图对象。
根视图内包含所有跟view controller有关的所有视图,通常会给根视图定义一个frame去匹配app window的size,frame应该是布满整个屏幕的。然而frame会根据你的view controller来调整它的display1️⃣。这个根视图可以是普通的UIView,也可以是自己的客户化的view,或者任何其他可以铺满屏幕的view。
2、创建子视图并且加入到根视图内
对于每个子视图都应该创建并且初始化,然后用addSubview:方法加入到父视图中去。
3、如果用了自动旋转布局模式,应该给每个视图配置足够多的位置限定条件。并且还要实现两个方法:viewWillLayoutSubviews和viewDidLayoutSubview来调整子类的frame。
4、添加根视图到view controller的property中。
下面的代码展示了如何创建视图和子视图
- (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.”
注意:用代码覆盖loadView方法去新建视图时,不可以调用super.初始化默认的view-loading行为,这通常会引起cpu的运行浪费。你自己的loadview方法的实现应该做所有需要的工作。