UIViewController:视图控制器
作用:
1.控制视图显⽰示,响应事件
2.分担AppDelegate的工作
3.实现模块独立,提高复用性
功能:
1.控制视图大小变换、布局视图、响应事件。
2.检测以及处理内存警告。
3.检测以及处理屏幕旋转。
4.检测视图的切换
MVC概述
UIViewController是MVC设计模式的核心。
MVC是一个框架级的设计模式。
M是Model,主要用于建立数据模型(即数据的结构)
V是View,我们能看到的所有控件都是view,view主要的功能是展示数据。
C是Controller控制器,主要是控制M和V的通信
为什么使用自定义视图类
UIViewController自带一个空的view,与需求不符合。
视图控制器只负责控制视图显示,响应事件
检测屏幕旋转
视图控制器本身能检测到屏幕的旋转,如果要处理屏幕旋转,需要重写几个方法:
1.supportedInterfaceOrientations(设置设备支持旋转的方向)
2.willRotateToInterfaceOrientation:duration:(暂停音乐、关闭视图交互等)
3.willAnimateRotationToInterfaceOrientation:duration:(添加⾃定义动画等)
4.didRotateFromInterfaceOrientation:(播放⾳乐、打开视图交互等)。
视图处理
注意视图控制器会自动调整view的⼤⼩以适应屏幕旋转,bounds被修改,触发view的layoutSubviews⽅法。
view重写layoutSubviews方法,根据设备方向,重新布局。
[UIApplication shareApplication].statusBarOrientation提供设备当前方向。
练习题
修改LoginView上视图的布局。
重写view的layoutSubviews方法。实现横屏时,三个控件显示在同一行。
横竖屏切换时,回收已经出现的键盘
处理内存警告
控制器能监测内存警告,以便我们避免内存不够引起的crash。
在定义的controller子类中重写didReceiveMemoryWarning⽅法。
释放暂时不使用的资源。(数据对象、图像)
练习题
重写didReceiveMemoryWarning方法。
NSLog输出__Function__
模拟内存警告:模拟器 -> 硬件 -> 模拟内存警告。查看方法执行
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//根视图已经加载过,根视图未显示
if ([self isViewLoaded] == YES && self.view.window
== nil) {
//将根视图销毁
self.view = nil;
}
}
容器视图控制器
常用方法
self.view显示:viewWillAppear: 和 viewDidAppear:
self.view消失:viewWillDisappear: 和 viewDidDisappear:
当self.view添加到父视图上时,执行appear方法: 当self.view从父视 图上移除时,执行disappear方法
演示执行顺序
定义FirstViewController、SecondViewController类,first作为window 的根视图控制器。
将SecondViewController的view添加到FirstViewController的view上。
将SecondViewController的view移除。
查看SecondViewController中4个⽅法的执行顺序
#import "rootViewController.h"
#define HEIGHT self.view.frame.size.height
#import "LTView.h"
#import "SecondViewController.h"
@interface rootViewController ()<UITextFieldDelegate>
@property(nonatomic, retain)NSMutableArray *arr;
@end
@implementation rootViewController
// 视图控制器的初始化方法,这个方法一般自己就调用了,不需要我们再额外的去调用.它可以用来初始化一些容器,比如数组,字典等
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.arr = [NSMutableArray array];
}
NSLog(@"%s", __FUNCTION__);
return self;
}
- (void)loadView
{
[super loadView];
[LTView load];
NSLog(@"%s", __FUNCTION__);
// 主要针对self.view 进行创建 属于懒人加载模式(lazyingloading)
}
#pragma mark 如果想重写父类的方法,首先先用super去调用父类的方法,这样可以保证原功能不变,然后在方法里再写新添加的功能
// 视图加载
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor magentaColor];
NSLog(@"%s", __FUNCTION__);
// 视图的创建和铺设都在viewDidLord方法里进行
// 铺3个testField
UITextField *textField1 = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 150, 40)];
textField1.layer.borderWidth = 1;
textField1.layer.cornerRadius = 10;
[self.view addSubview:textField1];
[textField1 release];
textField1.delegate = self;
UITextField *textField2 = [[UITextField alloc] initWithFrame:CGRectMake(100, 300, 150, 40)];
textField2.layer.borderWidth = 1;
textField2.layer.cornerRadius = 10;
[self.view addSubview:textField2];
[textField2 release];
textField2.delegate = self;
UITextField *textField3 = [[UITextField alloc] initWithFrame:CGRectMake(100, 400, 150, 40)];
textField3.layer.borderWidth = 1;
textField3.layer.cornerRadius = 10;
[self.view addSubview:textField3];
[textField3 release];
textField3.delegate = self;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 500, 150, 40);
[button setTitle:@"下页" forState:UIControlStateNormal];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
button.layer.borderWidth = 1;
button.layer.cornerRadius = 10;
// Do any additional setup after loading the view.
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// 整个是在移动self.view,父视图的移动会让所有的子视图一同移动,而且相对父视图的坐标位置不会发生变化,所以,可以沿用上一个方法的判断
// 只要输入框被激活,就会触发这方法
if (textField.frame.origin.y > HEIGHT / 2) {
// 先做一个差值
CGFloat height = textField.frame.origin.y - HEIGHT / 2;
self.view.center = CGPointMake(self.view.center.x, self.view.center.y - height);
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
// HIGHT 为view视图高度
if (textField.frame.origin.y > HEIGHT / 2) {
// 先做一个差值
CGFloat height = textField.frame.origin.y - HEIGHT / 2;
self.view.center = CGPointMake(self.view.center.x, self.view.center.y + height);
}
return YES;
}
// 右上角点击索引方法名 相当于在方法列表中添加注释
#pragma mark 视图将要出现
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%s", __FUNCTION__);
}
// 手动加警告 报黄
//#warning 这个方法是视图已经出现的意思
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%s", __FUNCTION__);
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"%s", __FUNCTION__);
}
- (void)click:(UIButton *)button
{
// [UIColor clearColor];
// CGFloat a = arc4random() % 256 / 255.0;
// CGFloat b = arc4random() % 256 / 255.0;
// CGFloat c = arc4random() % 256 / 255.0;
// self.view.backgroundColor = [UIColor colorWithRed:a green:b blue:c alpha:1];
// NSLog(@"%g,%g,%g", a, b, c);
// 创建一个secondVC对象
SecondViewController *secondVC = [[SecondViewController alloc] init];
// 设置一下跳转的时候动画效果
// [secondVC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[secondVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
// [secondVC setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
// [secondVC setModalTransitionStyle:UIModalTransitionStylePartialCurl];
// 进行跳转
[self presentViewController:secondVC animated:YES completion:^{
}];
[secondVC release];
}
// 监控当前内存信息
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [ UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(100, 100, 100, 30);
button.layer.borderWidth = 1;
button.layer.cornerRadius = 10;
[self.view addSubview:button];
[button setTitle:@"返回" forState:UIControlStateNormal];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
self.view.backgroundColor = [UIColor orangeColor];
// Do any additional setup after loading the view.
}
- (void)click:(UIButton *)button
{
// 点击返回,回到前一个页面
[self dismissViewControllerAnimated:YES completion:^{
// <#code#>
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#import <UIKit/UIKit.h>
@interface LTView : UIView<UITextFieldDelegate>
// 因为要在类的外面获取输入框的内容并修改Label的标题,所以把这两部分属性写在.h文件中
@property(nonatomic, retain)UILabel *MyLaber;
@property(nonatomic, retain)UITextField *MyTextField;
@end
#import "LTView.h"
@implementation LTView
// 重写默认的初始化方法
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 模块化
[self createView1];
// [self createView2];
}
return self;
}
- (void)createView1
{
// 创建两个子视图,一个是label,一个是textField
self.MyLaber = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 100, 40)];
self.MyLaber.backgroundColor = [UIColor orangeColor];
self.MyTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 100, 180, 40)];
self.MyTextField.backgroundColor = [UIColor cyanColor];
self.MyTextField.delegate = self;
[self addSubview:self.MyLaber];
[self addSubview:self.MyTextField];
[self.MyLaber release];
[self.MyTextField release];
}
- (void)createView2
{
self.MyLaber = [[UILabel alloc] initWithFrame:CGRectMake(50, 160, 100, 40)];
self.MyLaber.backgroundColor = [UIColor yellowColor];
[self addSubview:self.MyLaber];
[self.MyLaber release];
self.MyTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 160, 180, 40)];
self.MyTextField.backgroundColor = [UIColor blueColor];
[self addSubview:self.MyTextField];
[self.MyTextField release];
}
- (void)dealloc
{
[self.MyTextField release];
[self.MyLaber release];
[super dealloc];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
@end