UIView

(1)view基本介绍
先来看看官方API的解释:The UIView class defines a rectangular area on the screen
and the interfaces for managing the content in that area.
At runtime, a view object handles the rendering of any content in its area
and also handles any interactions with that content.(UIView在屏幕上定义了一个矩形区域和管理区域内容的接口。在运行时,一个视图对象控制该区域的渲染,同时也控制内容的交互。)。所以说UIView具有三个基本的功能,画图和动画,管理内容的布局,控制事件。正是因为UIView具有这些功能,它才能担当起MVC中视图层的作用。
UIView咋看起来很复杂,官方API中各种函数接口,要学过运用庖丁解牛的思想,逐个分析,因为再复杂的东西都是有简单的东西构成的。回到刚才提到的UIView的三个基本功能就可以容易的分离出UIView不同的功能是怎么组合起来的。首先看视图最基本的功能显示和动画,其实UIView的所有的绘图和动画的接口,都是可以用CALayer和CAAnimation实现的,也就是说苹果公司是不是把CoreAnimation的功能封装到了UIView中,这个文档中没有提到过,也没法断言。但是每一个UIView都会包含一个CALayer,并且CALayer里面可以加入各种动画。再次我们来看UIView管理布局的思想其实和CALayer也是非常的接近的。最后控制事件的功能,是因为UIView继承了UIResponder。经过上面的分析很容易就可以分解出UIView的本质。UIView就相当于一块白墙,这块白墙只是负责把加入到里面的东西显示出来而已。
这里写图片描述

(2)UIView及 UIView的子类的功能 :
1.管理矩形区域里的内容
2.处理矩形区域中的事件
3.子视图的管理
4.还能实现动画

3)视图的最基本属性
frame和center都是相对于父视图的,bounds是相对于自身的

frame 是CGRect frame的origin是相对于父视图的左上角原点(0,0)的位置,改变视图的frame会改变center
center 是CGPoint 指的就是整个视图的中心点,改变视图的center也会改变frame
bounds 是CGRect 是告诉子视图本视图的原点位置(通俗的说就是,子视图的frame的origin与父视图的bounds的origin的差,就是子视图相对于父视图左上角的位置,如果结果为负,则子视图在父视图外)
4)几个基本界面元素:window(窗口)、视图(view)

1.UIView

下面来认识一下UIView类,这个类继承自UIResponder,看这个名字我们就知道它是负责显示的画布,如果说把window比作画框的话。我们就是不断地在画框上移除、更换或者叠加画布,或者在画布上叠加其他画布,大小当然 由绘画者来决定了。有了画布,我们就可以在上面任意施为了
UIView* myView =[[ UIView alloc]initWithFrame:CGRectMake(0.0,0.0,200.0,400.0)]; //这里创建了一块画布,定义了相对于父窗口的位置, 以及大小。

2.UIWindow

UIWindow继承自UIView,关于这一点可能有点逻辑障碍,画框怎么继承自画布呢?不要过于去专牛角尖,画框的形状不就是跟画布一样吗?拿一块画布然后用一些方法把它加强,是不是可以当一个画框用呢?这也是为什么 一个view可以直接加到另一个view上去的原因了。
看一下系统的初始化过程(在application didFinishLauchingWithOptions里面):

self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor grayColor]; //给window设置一个背景色

[self.window makeKeyAndVisible]; //让window显示出来

3.UIScreen类代表了屏幕,通过这个类我们可以获取一些和屏幕相关的内容

CGRect screenBounds = [ [UIScreen mainScreen]bounds]; //返回的是带有状态栏的Rect
CGRect viewBounds = [ [UIScreen mainScreen]applicationFrame]; //不包含状态栏的Rect

//screenBounds 与 viewBounds 均是相对于设备屏幕来说的
//所以 screenBounds.origin.x== 0.0 ; screenBounds.oringin.y = 0.0;
screenBounds.size.width == 320; screenBounds.size.height == 480(或者其他分辨率有所差异)
//所以 screenBounds.origin.x== 0.0 ; screenBounds.oringin.y = 20.0;(因为状态栏的高度是20像素) screenBounds.size.width == 320; screenBounds.size.height == 480
//取得StatusBar的位置和大小
[self.view addSubview:theToolbar];
CGRect statusBarRect = [[UIApplication sharedApplication]statusBarFrame];

NSLog(@\”%@\”, NSStringFromCGRect(statusBarRect));

5)UIView的方法
一个 UIView 里面可以包含许多的 Subview(其他的 UIView),而这些 Subview 彼此之间是有所谓的阶层关系,这有点类似绘图软体中图层的概念。

1.首先是大家最常使用的新增和移除Subview。
[Subview removeFromSuperview]; //将Subview从当前的UIView中移除
[UIView addSubview:Subview]; //替UIView增加一个Subview

2.在UIView中将Subview往前或是往后移动一个图层,往前移动会覆盖住较后层的 Subview,而往后移动则会被较上层的Subview所覆盖。
[UIView bringSubviewToFront:Subview]; //将Subview往前移动一个图层(与它的前一个图层对调位置)//将Subview往前移动一个图层(与它的前一个图层对调位置)
[UIView sendSubviewToBack:Subview]; //将Subview往后移动一个图层(与它的后一个图层对调位置)

3.在UIView中使用索引Index交换两的Subview彼此的图层层级。
[UIView exchangeSubviewAtIndex:indexA withSubviewAtIndex:indexB]; //交换两个图层

4.使用Subview的变数名称取得它在UIView中的索引值(Index )。
NSInteger index = [[UIView subviews] indexOfObject:Subview名称]; //取得Index

5.替Subview加上NSInteger 的註记(Tag)好让之后它们分辨彼此。
[Subview setTag:NSInteger]; //加上标记
[UIView viewWithTag:NSInteger]; //通过标记得到view 返回值为UIView

6.最后是取得UIView中所有的Subview,调用此方法会传回一个 NSArray,并以由后往前的顺序列出这些 Subview。
[UIView subviews] ; //取的UIView下的所有Subview

UIView的生命周期
一、视图层次和根视图
   任何应用有且只有一个 UIWindow 对象。 UIWindow 对象就像是一个容器,负责包含应用中的所有的视图。应用需要在启动时创建并设置 UIWindow 对象,然后为其添加其他视图。加入窗口的视图会成为该窗口的子视图。窗口的子视图还可以有自己的子视图,从而构成一个以 UIWindow 对象为根视图的,类似于树形结构的视图层次结构。
视图层次结构形成之后,系统会将其绘制到屏幕上,绘制过程可以分为两步:
 1. 层次结构中的每个视图(包括 UIWindow 对象)分别绘制自己。视图会将自己绘制到图层( layer )上,每个 UIView 对象都有一个 layer 属性,指向一个 CALayer 类的对象
2. 所有视图的图层何曾一幅图像,绘制到屏幕上。
获取当前应用程序的 UIWindow 方法是 UIWindow * keyWindow = [UIApplication sharedApplication].keyWindow;

二、视图的加载方式
UIViewController采用懒加载的方式加载它的视图,也就是说第一次访问到控制器的view属性时,才会加载或创建它。因为师徒由控制其管理,所以说到视图的加载方式时,主要讨论的是视图控制器的加载方式。
•通过Storyboard加载:这是苹果推荐的方式,也是未来的趋势。 
通过这种方式创建UIViewController对象的话,首先生成UIStoryboard类型的对象,然后调用这个对象的instantiateViewControllerWithIdentifier:方法
•通过Nib文件加载:
Nib文件其实就是xib文件,Storyboard相当于是聚合了多个nib文件,并且添加了对不同的UIViewController之间的segue和relationship的管理。但总的实现原理非常类似
通过这种方式加载视图,需要调用UIViewController类的initWithNibName:bundle:方法
•通过loadview方法加载:
这就是通过代码加载。这需要我们在loadView 方法中,通过编程创建自己的视图层次,并且把把根视图赋值给UIViewController的view属性。
因此,通过代码自定义View的时候,loadView 方法大概是这样的:

    - (void)loadView{
        self.view = [[XXXView alloc] init];
    }

三、处理视图的相关通知

当视图切换(可见行发生变化)时,视图控制器会自动调用一系列方法来响应变化。

- (void)viewDidLoad;
- (void)viewWillAppear:(BOOL)animated; 
- (void)viewDidAppear:(BOOL)animated;
- (void)viewWillDisappear:(BOOL)animated; 
- (void)viewDidDisappear:(BOOL)animated; 
-(void)viewWillLayoutSubviews
-(void)viewDidLayoutSubviews

当显示一个视图时,上面的方法的调用顺序是viewDidLoad->viewWillAppear->viewWillLayoutSubviews->viewDidLayoutSubviews->viewDidAppear
四、在运行时展示View

通过storyboard文件中的信息实例化视图
连接outlet和action
把根视图赋值给UIViewController的view属性(其实是调用loadView方法)
调用UIViewController的awakeFromeNib方法
调用UIViewController的viewDidLoad方法(此时已经完成视图的加载工作)

调用UIViewController的viewWillAppear方法。
系统更新视图的布局
视图将自己显示到屏幕上
调用UIViewController的viewDidAppear方法。

五、视图的生命历程

整个流程梳理一遍。

-[ViewController initWithCoder:]或-[ViewController initWithNibName:Bundle]:首先从归档文件中加载UIViewController对象。即使是纯代码,也会把nil作为参数传给后者。
-[UIView awakeFromNib]:作为第一个方法的助手,方便处理一些额外的设置。
-[ViewController loadView]:创建或加载一个view并把它赋值给UIViewController的view属性
-[ViewController viewDidLoad]:此时整个视图层次(view hierarchy)已经被放到内存中,可以移除一些视图,修改约束,加载数据等
-[ViewController viewWillAppear:]:视图加载完成,并即将显示在屏幕上,还没有设置动画,可以改变当前屏幕方向或状态栏的风格等。
-[ViewController viewWillLayoutSubviews]:即将开始子视图位置布局
-[ViewController viewDidLayoutSubviews]:用于通知视图的位置布局已经完成
-[ViewController viewDidAppear:]:视图已经展示在屏幕上,可以对视图做一些关于展示效果方面的修改。
-[ViewController viewWillDisappear:]:视图即将消失
-[ViewController viewDidDisappear:]:视图已经消失
如果考虑UIViewController可能在某个时刻释放整个view。那么再次加载视图时显然会从步骤3开始。因为此时的UIViewController对象依然存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员的修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值