iOS学习22之视图控制器
1.自定义视图
1> 概述
定义视图:系统标准UI之外,自己组合而出的新的视图。
定义视图的优点:
iOS提供了很多UI组件,借助它们我们可以实现不同的功能。尽管如此,实际开发中,我们还需要自定义视图。积累自己的代码库,方便开发。自己封装的视图,能像系统UI控件一样,用于别的项目中,能大大降低开发成本,提高开发效率。
高质量代码的特点:可复用,可移植,精炼等。(高内聚,低耦合)
2> 自定义视图步骤(以登录框为例(LTView))
根据需求的不同,自定义视图继承的类也有所不同。一般自定义的视图会继承于UIView。以下是自定义视图的要点:
① 创建一个UIView子类: @interface LTView : UIView
② 在类的初始化方法中添加子视图。
// 添加视图
- (void)addAllViews
{
// leftLabel
self.leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(kLabelX, kLabelY, , )];
// 文本对齐
self.leftLabel.textAlignment = NSTextAlignmentCenter;
// 添加到自定义视图
[self addSubview:self.leftLabel]; // rightTextField
self.rightTextField = [[UITextField alloc] initWithFrame:
CGRectMake(CGRectGetMaxX(self.leftLabel.frame) + kSpace,
CGRectGetMinY(self.leftLabel.frame),
self.frame.size.width - CGRectGetWidth(self.leftLabel.frame) - kSpace - kLabelX * ,
CGRectGetHeight(self.leftLabel.frame))];
// 设置边框样式
self.rightTextField.borderStyle = UITextBorderStyleRoundedRect;
// 添加到自定义视图
[self addSubview:self.rightTextField];
}
③ 类的.h文件提供一些接口(方法),便于外界操作子视图。
#import <UIKit/UIKit.h> @interface LTView : UIView // .h文件声明属性,为了方便和外界通信
@property (nonatomic, strong) UILabel *leftLabel;
@property (nonatomic, strong) UITextField *rightTextField; @end
④ 此时的 LTView 就变成了一个具有 label 和 textField 的视图了。
3> LTView在AppDelegate.m中的具体使用
// 用户名
LTView *userLTView = [[LTView alloc] initWithFrame:CGRectMake(, , self.window.frame.size.width - , )]; // 设置属性
userLTView.backgroundColor = [UIColor lightGrayColor];
userLTView.leftLabel.text = @"用户名";
userLTView.leftLabel.backgroundColor = [UIColor redColor];
userLTView.rightTextField.placeholder = @"请输入用户名";
userLTView.rightTextField.backgroundColor = [UIColor redColor]; // 设置代理
userLTView.rightTextField.delegate = self; // 添加父视图
[self.window addSubview:userLTView]; // 密码
ZF_LTView *pwLTview = [[ZF_LTView alloc] initWithFrame:
CGRectMake(CGRectGetMinX(userLTView.frame),
CGRectGetMaxY(userLTView.frame) + ,
CGRectGetWidth(userLTView.frame),
CGRectGetHeight(userLTView.frame))]; // 设置属性
pwLTview.backgroundColor = [UIColor lightGrayColor];
pwLTview.leftLabel.text = @"密码";
pwLTview.rightTextField.placeholder = @"请输入密码";
pwLTview.rightTextField.secureTextEntry = YES; // 添加到父视图
[self.window addSubview:pwLTview];
效果图
2.视图控制器
1> 概述
视图控制器是应用程序数据和视图之间的重要桥梁,每个iOS应用程序只显示一个用户界面,显示的内容是由控制器或一组视图控制器协调管理。所以,视图控制器提供了一个基本的框架来构建应用程序。
UIViewController是所有视图控制器的父类。
iOS提供了许多内置的视图控制器,以支持标准的用户界面部分,比如导航控制器(UINavigationController),标签控制器 (UITabBarController), 表视图控制器(UITableViewController)等。
2> 视图控制器的功能
- 控制视图大小变换、布局视图、响应事件。
- 检测以及处理内存警告。
- 检测以及处理屏幕旋转。
- 检测视图的切换。
- 实现模块独立,提高复用性。
3> 视图控制器的使用
① 定义UIViewController的子类:
@interface LoginViewController:UIViewController
② 在APPDelegate里创建视图控制器对象,作为window的根视图控制器:
// 创建window
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor redColor];
[self.window makeKeyAndVisible];
// 设置根视图控制器
self.window.rootViewController = [[LoginViewController alloc] init];
③ 在viewDidLoad方法中使用默认创建好的视图对象view:
#pragma mark 视图加载完毕
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
NSLog(@"%s %d", __FUNCTION__, __LINE__);
// Do any additional setup after loading the view.
}
4> 视图控制器生命周期
viewDidLoad --> viewWillAppear --> viewDidAppear --> viewWillDisappear --> viewDidDisappear
@implementation ViewController // 视图已经加载
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. NSLog(@"1 %s__%d", __FUNCTION__, __LINE__);
} // 视图将要出现
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"2 %s__%d", __FUNCTION__, __LINE__);
}
// 视图将要消失
- (void)viewWillDisappear:(BOOL)animated {
NSLog(@"3 %s__%d", __FUNCTION__, __LINE__);
}
// 视图已经出现
- (void)viewDidAppear:(BOOL)animated {
NSLog(@"4 %s__%d", __FUNCTION__, __LINE__);
}
// 视图已经消失
- (void)viewDidDisappear:(BOOL)animated {
NSLog(@"5 %s__%d", __FUNCTION__, __LINE__);
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
3.视图控制器指示视图
设置步骤
自定义视图类继承UIView。在初始化方法中添加子视图控件。
// 重写initWithFrame
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor yellowColor]; [self addAllViews];
}
return self;
} // 添加视图
- (void)addAllViews
{
/**
* 布局: userLabel userTextField loginButton
* 事件: 代理事件 按钮点击事件 (controller实现)
* @return nil
*/ // 布局userLabel
self.userLabel = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
self.userLabel.text = @"用户名";
self.userLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.userLabel]; // 布局userTextField
self.userTextField = [[UITextField alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.userLabel.frame) + , CGRectGetMinY(self.userLabel.frame), , )];
self.userTextField.borderStyle = UITextBorderStyleRoundedRect;
self.userTextField.placeholder = @"请输入用户名";
[self addSubview:self.userTextField]; // 布局loginButton
self.loginButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.loginButton.backgroundColor = [UIColor cyanColor];
self.loginButton.frame = CGRectMake(, CGRectGetMaxY(self.userTextField.frame) + kSpace, CGRectGetWidth(self.frame) - , );
[self.loginButton setTitle:@"登 录" forState:UIControlStateNormal]; self.loginButton.tintColor = [UIColor whiteColor];
self.loginButton.layer.cornerRadius = ; [self addSubview:self.loginButton];
}
重写controller的loadView方法。创建自定义视图对象,并指定为controller的view。(注:loadView方法在控制器的view为nil的时候被调用,用于以编程的方式创建view的时候用到。loadView是使用代码生成视图的时候,当视图第一次载入的时候调用的方法,用于使用(写)代码来实现控件。)
// 加载视图
// 使用控制器指定自定义view(也就是替换控制器的view)
// self.view没有被创建对象,节省内存
- (void)loadView
{
// 初始化自定义视图
self.loginView = [[LoginView alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 使用自定义视图替换控制器视图
self.view = self.loginView;
}
将子视图控件对象设置为自定义视图类的属性,在viewDidLoad方法中进行设置:添加action、设置delegate等等。
// 处理事件一般都是在这个函数中实现
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 处理事件 // 1. 代理事件
self.loginView.userTextField.delegate = self; // 2.按钮点击事件
[self.loginView.loginButton addTarget:self action:@selector(loginButtonClick) forControlEvents:UIControlEventTouchUpInside];
}
在controller中添加按钮点击事件实现和代理方法的实现。
#pragma mark loginButtonClick Method (实现按钮点击方法) - (void)loginButtonClick
{
NSLog(@"别点我...");
SecondViewController *secondVC = [[SecondViewController alloc] init]; [self presentViewController:secondVC animated:YES completion:nil]; } #pragma mark UITextFieldDelegate Method (代理方法实现) // 点击return回收键盘
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
} // 触摸屏幕回收键盘
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
4.MVC
1> 概述
UIViewController是MVC设计模式的核心。
MVC是一个框架级的设计模式。
M是Model,主要用于建立数据模型(即数据的结构)。
V是View,我们能看到的所有控件都是view,view主要的功能是展示数据
C是控制器,主要是控制M和V的通信。
2> iOS中的MVC
5.屏幕旋转
1> 检测屏幕旋转
视图控制器本身能检测到屏幕的旋转,如果要处理屏幕旋转,需要重写几个方法:
supportedInterfaceOrientations(设置设备支持旋转的方向,如果不添加,视图控制器将无法检测屏幕的旋转)。
willRotateToInterfaceOrientation:duration:(暂停音乐、关闭视图交互等)。
willAnimateRotationToInterfaceOrientation:duration:(添加自定义动画等)。
didRotateFromInterfaceOrientation:(播放音乐、打开视图交互等)。
#pragma mark 检测屏幕旋转
// 屏幕所支持的样式
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
// 支持所有的方向
return UIInterfaceOrientationMaskAll;
}
2> 视图处理
注意视图控制器会自动调整view的大小以适应屏幕旋转,bounds被修改,触发view的layoutSubviews方法。
view重写layoutSubviews方法,根据设备方向,重新布局。
[UIApplication sharedApplication].statusBarOrientation提供设备当前方向。
// 布局子视图:当屏幕旋转的时候,可以重新布局子视图的位置
- (void)layoutSubviews
{
// 如果是竖屏(UIInterfaceOrientationPortrait)的话,保持原来的尺寸
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
self.loginButton.frame = CGRectMake(, CGRectGetMaxY(self.userTextField.frame) + kSpace, CGRectGetWidth(self.frame) - , );
} else { // 否则横屏改变位置
self.loginButton.frame = CGRectMake(, CGRectGetMaxY(self.userTextField.frame) + kSpace, , );
}
}
6.内存警告
1> 概述
内存警告来源:手机内存80M,程序运行过程中内存接近80M时程序会为每一个视图控制器发送内存警告消息。
如何处理:
① 控制器能监测内存警告,以便我们避免内存不够引起的crash。
② 在定义的controller子类中重写didReceiveMemoryWarning方法。
③ 释放暂时不使用的资源(self.view及view的子视图例如数据对象、图 像)。
2> 代码
// 当接收内存警告的时候都会走这个方法
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
NSLog(@"%s__%d", __FUNCTION__, __LINE__);
}
iOS学习22之视图控制器的更多相关文章
- iOS Programming View Controllers 视图控制器
iOS Programming View Controllers 视图控制器 1.1 A view controller is an instance of a subclass of UIVi ...
- iOS CoCoa编程中视图控制器与视图类(转)
分类: iPhone2012-05-28 11:19 837人阅读 评论(0) 收藏 举报 cocoa编程iosuinavigationcontrolleruiviewiphone iPhone编程规 ...
- IOS 学习笔记(3) 视图UITabbarController
1.UITabbarViewController标签试图控制器.由于标签页本就起着分类的作用,所以往往呈现的视图内容之间,可以是毫不相关的功能. UITabbarViewController仍然继承自 ...
- IOS 学习笔记(2) 视图UINavigationController
1.栈 导航控制器自身有一个针对显示内容的栈,也有一个对于导航栏的栈,当有新的内容欲显示时,进的导航栏和显示内容会被压入此栈,这样原本显示中的导航栏和显示内容则会进入到栈的更深一层中,根据栈的先进后出 ...
- Step by Step iOS Project In Action - 视图控制器
1. 什么是视图控制器(View Controller) 简单来说,视图控制器用来管理你所有的视图. 他们是你的视图和模型的粘合剂. 如果你做过MVC的Web项目,我想你应该不会对它感到陌生. 2. ...
- Snail—UI学习之导航视图控制器UINavigationController(系统)
背景 有一个根视图控制器 然后跳转到第一个界面 第一个界面能够返回到根视图 也能够跳转到第二个视图 第二个视图能够直接返回到根视图 新建三个ViewController RootViewCon ...
- iOS学习笔记——滚动视图(scrollView)
滚动视图:在根视图中添加UIScrollViewDelegate协议,声明一些对象属性 @interface BoViewController : UIViewController<UIScro ...
- [ios学习笔记之视图、绘制和手势识别]
一 视图 二 绘制 三 手势 00:31 UIGestureRecognizer 抽象类 两步 1添加识别器(控制器或者视图来完成) 2手势识别后要做的事情 UIPanGestureRecognize ...
- iOS学习之自定义视图时,在屏幕发生旋转时触发重新布局方法
如果要对自定义的视图在屏幕旋转时重新布局,则在自定义视图中定义以下触发方法: -(void)layoutSubviews { [super layoutSubviews]; //1.获取到屏幕旋转的方 ...
随机推荐
- RxJava学习入门
RxJava是什么 一个词:异步. RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-bas ...
- hadoop 2.5 hdfs namenode –format 出错Usage: java NameNode [-backup] |
在 cd /home/hadoop/hadoop-2.5.2/bin 下 执行的./hdfs namenode -format 报错[hadoop@node1 bin]$ ./hdfs nameno ...
- 关于配置Spring框架的多个propertyConfigurer的问题
http://blog.csdn.net/aa427/article/details/38375259
- MVC:Control与View传值
MVC页面传值的方式主要有三种: 第一种: 采用ViewData.采用键值对的方式,ViewData存储的是一个object类型,传到view层需要强类型转换:使用起来类似于字典集合模式: ViewD ...
- Oracle的thin驱动和oci驱动有什么不同?哪个性能好些?
OCI:要安装ORACLE客户端,移植性略差,理论上性能好些 THIN:属于TYPE4,纯JAVA实现,移植性好,理论上性能略差些 推荐:最好还是使用THIN DRIVER吧,移植性好些,使用起来 ...
- [Win32命令行] 更改提示符字符串(PS1)
当进入的目录比较深时, cmd的提示符几乎会占据整行, 很烦, 于是Google之... 参考: A better PROMPT for CMD.EXE ... 更改方式: 1. pro ...
- 【数据结构】建立和平衡AVL二叉树
一步一步写平衡二叉树(AVL树) 原文地址:http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html 我添加了一些内容,以充实整个算 ...
- HDU5792 World is Exploding(树状数组)
一共6种情况,a < b且Aa < Ab, c < d 且Ac > Ad,这两种情况数量相乘,再减去a = c, a = d, b = c, b = d这四种情况,使用树状数组 ...
- HYSBZ 2440 完全平方数(莫比乌斯反演)
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2440 若i为质数,n为i*i的倍数,则称n为含平方因子数. 求1~n的无平方因子数. F(x) ...
- PMP 第六章 项目时间管理
定义活动 排列活动顺序 估算活动资源 估算活动持续时间 制定进度计划 控制进度计划 1.进度管理计划和进度计划的内容分别是什么,有什么区别? 进度计划:项目各活动计划完成日期的编排. 进度管理计 ...