ios开发之UIView和UIViewController
UIView 表示屏幕上的一块矩形区域,负责渲染区域的内容,并且响应该区域内发生的触摸事件。它在 iOS App 中占有绝对重要的地位,因为 iOS 中几乎所有可视化控件都是 UIView 的子类。
UIView 可以负责以下几种任务:
- 绘制和动画
- 布局和子视图管理
- 事件处理
绘制和动画
视图绘制
UIView 是按需绘制的,当整个视图或者视图的一部分由于布局变化,变成可见的,系统会要求视图进行绘制。对于那些需要使用 UIKit 或者 CoreGraphics 进行自定义绘制的视图,系统会调用 drawRect: 方法进行绘制。
当视图内容发生变化时,需要调用 setNeedsDisplay 或者 setNeedsDisplayInRect: 方法,告诉系统该重新绘制这个视图了。调用这个方法之后,系统会在下一个绘制周期更新这个视图的内容。由于系统要等到下一个绘制周期才真正进行绘制,可以一次性对多个视图调用 setNeedsDisplay,它们会同时被更新。
视图的几何属性
视图有 frame,center,bounds 等几个基本几何属性,其中:
- frame 使用的最多,其坐标位置都是相对于父视图的,可以用于确定本视图在父视图中的位置和其自身的大小
- center 的坐标位置也是相对于父视图的,通常用于移动,旋转等动画操作
- bounds 是相对于自身的,通常情况下就是(0,0,width,height), bounds 的含义可以认为是当前 view 被允许绘制的范围
视图的 ContentMode
视图在初次绘制完成后,系统会对绘制结果进行快照,之后尽可能地使用快照,避免重新绘制。如果视图的几何属性发生改变,系统会根据视图的 contentMode 来决定如何改变显示效果。
默认的 contentMode 是 UIViewContentModeScaleToFill ,系统会拉伸当前的快照,使其符合新的 frame 尺寸。大部分 contentMode 都会对当前的快照进行拉伸或者移动等操作。如果需要重新绘制,可以把 contentMode 设置为 UIViewContentModeRedraw,强制视图在改变大小之类的操作时调用drawRect:重绘。
动画
可以以动画的形式改变视图的下面这些属性,只需要告诉系统动画开始和结束时的数值,系统会自动处理中间的过渡过程。
frame
bounds
center
transform
alpha
backgroundColor
contentStretch
布局和子视图管理
除了提供视图本身的内容之外,一个视图也可以表现得像一个容器。当一个视图包含其他视图时,两个视图之间就创建了一个父子关系。在这个关系中子视图被称为 subView ,父视图被称为 superView 。一个视图可以包含多个子视图,它们被存放在这个视图的 subviews 数组里。添加,删除,以及操作这些子视图的相对位置的函数如下:
addSubview:
insertSubview:...
bringSubviewToFront:
sendSubviewToBack:
exchangeSubviewAtIndex:withSubviewAtIndex:
removeFromSuperview(子视图调用)
AutoResizing 和 Constraint
当一个视图的大小改变时,它的子视图的位置和大小也需要相应地改变。UIView 支持自动布局,也可以手动对子视图进行布局。
当下列这些事件发生时,需要进行布局操作:
- 视图的 bounds 大小改变#
- 用户界面旋转,通常会导致根视图控制器的大小改变
- 视图的 layer 层的 Core Animation sublayers 发生改变
- 程序调用视图的
setNeedsLayout或layoutIfNeeded方法 - 程序调用视图 layer 的
setNeedsLayout方法
Auto Resizing
视图的autoresizesSubviews属性决定了在视图大小发生变化时,如何自动调节子视图。
可以使用的掩码如下:
UIViewAutoresizingNone
UIViewAutoresizingFlexibleHeight
UIViewAutoresizingFlexibleWidth
UIViewAutoresizingFlexibleLeftMargin
UIViewAutoresizingFlexibleRightMargin
UIViewAutoresizingFlexibleBottomMargin
UIViewAutoresizingFlexibleTopMargin
可以通过位运算符将它们组合起来,例如 UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth。
Constraint
Constraint 是另一种用于自动布局的方法。本质上,Constraint 就是对 UIView 之间两个属性的一个约束:
attribute1 == multiplier × attribute2 + constant
其中方程两边不一定是等于关系,也可以是大于等于之类的关系。
Constraint 比 AutoResizing 更加灵活和强大,可以实现复杂的子视图布局。
自定义 layout
UIView 当中提供了一个 layoutSubviews 函数,UIView 的子类可以重载这个函数,以实现更加复杂和精细的子 View 布局。
苹果文档专门强调了,应该只在上面提到的 Autoresizing 和 Constraint 机制不能实现所需要的效果时,才使用 layoutSubviews。而且,layoutSubviews 方法只能被系统触发调用,程序员不能手动直接调用该方法。
那么 layoutSubviews 方法具体调用的时机有哪些呢?具体有下面几种情况:
- 在父 view 的 autoresize mask 为 ON 的情况下,addSubview 会导致被 add 的 view 调用 layoutSubviews, 同时 add 的 target view 以及它所有的子 view 都会被调用。
- setFrame 当新的 frame 和 旧的不同时(即 view 的大小改变时)会调用 layoutSubviews
- 滚动一个 UIScollView 会导致这个 scrollView 以及它的父 View 调用 layoutSubviews
- 旋转设备会导致当前所响应的 ViewController 的主 View 调用 layoutSubviews
- 改变 View 的 size 会导致父 View 调用 layoutSubviews
- removeFromSuperview 也会导致父 View 调用 layoutSubviews
事件处理
UIView 是 UIResponder 的子类,可以响应触控事件。
通常可以使用 addGestureRecognizer: 添加手势识别器来响应触控事件,如果需要手动处理,则按需要重载 UIView 中的下面四个函数:
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
UIViewController(视图控制器),顾名思义,是 MVC 设计模式中的控制器部分。UIViewController 在 UIKit 中主要功能是用于控制画面的切换,其中的 view 属性(UIView 类型)管理整个画面的外观。
UIViewController 生命周期
ViewController 生命周期的第一步是初始化。不过具体调用的方法还有所不同。如果使用 StoryBoard 来创建 ViewController,我们不需要显式地去初始化,Storyboard 会自动使用 initWithCoder: 进行初始化。如果不使用 StoryBoard,我们可以使用 init: 函数进行初始化,init: 函数在实现过程中还会调用 initWithNibName:bundle:。 我们应该尽量避免在 VC 外部调用 initWithNibName:bundle:,而是把它放在 VC 的内部(参考这里)。
初始化完成后,VC 的生命周期会经过下面几个函数:
(void)loadView
(void)viewDidLoad
(void)viewWillAppear
(void)viewWillLayoutSubviews
(void)viewDidLayoutSubviews
(void)viewDidAppear
(void)viewWillDisappear
(void)viewDidDisappear
假设现在有一个 AViewController(简称 Avc) 和 BViewController (简称 Bvc),通过 navigationController 的 push 实现 Avc 到 Bvc 的跳转,下面是各个方法的执行执行顺序:
. A viewDidLoad
. A viewWillAppear
. A viewDidAppear
. B viewDidLoad
. A viewWillDisappear
. B viewWillAppear
. A viewDidDisappear
. B viewDidAppear
如果再从 Bvc 跳回 Avc,会产生下面的执行顺序:
. B viewWillDisappear
. A viewWillAppear
. B viewDidDisappear
. A viewDidAppear
可见 viewDidLoad 只会调用一次,再第二次跳回 Avc 的时候,AViewController 仍然存在于内存中,也就不需要 load 了。
注意上面的生命周期中都没有提到有关 ViewController 销毁的内容,在 iOS 4 & 5 中 ViewController 中有一个 viewDidUnload 方法。当内存不足,应用收到 Memory warning 时,系统会自动调用当前没在界面上的 ViewController 的 viewDidUnload 方法。 通常情况下,这些未显示在界面上的 ViewController 是 UINavigationController Push 栈中未在栈顶的 ViewController,以及 UITabBarViewController 中未显示的子 ViewController。这些 View Controller 都会在 Memory Warning 事件发生时,被系统自动调用 viewDidUnload 方法。
从 iOS 6 开始,viewDidUnload 方法被废弃掉了,应用受到 memory warning 时也不会再调用 viewDidUnload 方法。我们可以通过重载 - (void)didReceiveMemoryWarning 和 -(void)dealloc 来进行清理工作。
ios开发之UIView和UIViewController的更多相关文章
- ios开发之UIView的frame、bounds跟center属性的区别(附图)
博文暂时想到什么写什么,不顺理成章,不顺章成篇. 先看几个概念 坐标点Poit:向右侧为X轴正方向的值x,原点下侧为Y轴正方向的值y 大小Size:由宽度width和高度height构成,表示一个矩形 ...
- IOS开发之UIView的基本使用
一.视图 1. iphone手机上的窗口就是UIWindow类的一个实例(1个手机应用只有一个UIWindow). 2.UIView类用于实现视图. UIView提供了方法来添加和删除子视图.一个视图 ...
- IOS开发之UIView总结
如果想调用某个类的某个方法可以写成这样,这个方法来自NSObject类 performSelector: performSelector:withObject: performSelector:wit ...
- iOS开发之UIView的常见属性
1.所有控件都继承自UIView,UIView的常见属性如下: @property(nonatomic,readonly) UIView *superview;获得自己的父控件对象 @property ...
- IOS开发之UIView总结1
太长了,请看 http://blog.csdn.net/xdrt81y/article/details/9128695 performSelector: performSelector:withObj ...
- iOS开发之UIView
在iPhone里你能看到的.摸到的,都是UIView. 视图坐标系统: UIKit中的坐标都是基于这样的坐标系统:以左上角为坐标的原点,原点向下和向右为坐标轴方向. 坐标值由浮点数来表示,内容的布局和 ...
- iOS开发之loadView、viewDidLoad及viewDidUnload的关系
iOS开发之loadView.viewDidLoad及viewDidUnload的关系 iOS开发之loadView.viewDidLoad及viewDidUnload的关系 标题中所说的3个方 ...
- iOS开发之UISearchBar初探
iOS开发之UISearchBar初探 UISearchBar也是iOS开发常用控件之一,点进去看看里面的属性barStyle.text.placeholder等等.但是这些属性显然不足矣满足我们的开 ...
- iOS开发之WKWebView简单使用
iOS开发之WKWebView简单使用 iOS开发之 WKWebVeiw使用 想用UIWebVeiw做的,但是突然想起来在iOS8中出了一个新的WKWebView,算是UIWebVeiw的升级版. ...
随机推荐
- 脚本_备份mysql
#!bin/bash#功能:备份mysql数据 #作者:liusingbon#定义变量 user(数据库用户名),passwd(数据库密码),date(备份的时间标签)#dbname(需要备份的数据库 ...
- KMP,Trie,AC自动机题目集
字符串算法并不多,KMP,trie,AC自动机就是其中几个最经典的.字符串的题目灵活多变也有许多套路,需要多做题才能体会.这里收集了许多前辈的题目做个集合,方便自己回忆. KMP题目:https:// ...
- categorical_crossentropy VS. sparse_categorical_crossentropy
From:https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/ categorical_crossentropy 和 sp ...
- ubuntu安装deb包(dpkg)
安装 sudo dpkg -i DEB_PACKAGE 卸载 sudo dpkg -r PACKAGE_NAME 重新配置已安装的包 Reconfigure an existing package 例 ...
- JDK1.7 hashMap源码分析
了解HashMap原理之前先了解一下几种数据结构: 1.数组:采用一段连续的内存空间来存储数据.对于指定下标的查找,时间复杂度为O(1),对于给定元素的查找,需要遍历整个数据,时间复杂度为O(n).但 ...
- php基于SQLite实现的分页功能示例
php基于SQLite实现的分页功能. 这里操作数据库文件使用的是前面文章<PHP基于PDO实现的SQLite操作类>中的SQLite数据库操作类. 代码: <?php class ...
- Radical and array
Radical and array 时间限制: 1 Sec 内存限制: 128 MB提交: 46 解决: 27[提交][状态] 题目描述 Radical has an array , he wan ...
- iOS 获取全局唯一标示符
这个方法用来产生一个唯一的标示符,每次调用都会不一样,所以可以用当作一些临时缓存文件的名字 NSString *identifier = [[NSProcessInfo processInfo] gl ...
- MongoDB(7):集群部署实践,包含复制集,分片
注: 刚开始学习MongoDB,写的有点麻烦了,网上教程都是很少的代码就完成了集群的部署, 纯属个人实践,错误之处望指正!有好的建议和资料请联系我QQ:1176479642 集群架构: 2mongos ...
- ASP.NET免费发送邮件|
因为之前有做过邮件发送的项目,最近也看一些朋友问起这个的做法,现在拿来给大家查看下.因为那时候是公司的服务器配置的.所以后来自己便在网上找到了一个可以任何个人都是可以使用的邮件发送.小弟新手,高手看到 ...