从后往前传 —— 代理传值
代理传值 (代理是前一个界面, 协议在后一个界面写, 后一个界面是委托方, 前一个界面是被委托方.)
一 : 在后一个界面定义协议 (定义一个用于传值的方法, 而且方法必须要有参数, 参数类型要与所传数据的类型保持一致)
二 : 在后一个界面定义代理属性, 用来保存代理对象.
三 : 设置后一个界面的代理 -- 在前一个界面进入后一个界面之前, 设置前一个界面为后一个界面的代理.
四 : 前一个界面服从协议.
五 : 前一个界面实现协议中的方法.
六 : 后一个界面让代理执行协议中的方法 (执行方法时, 把传输的数据作为方法的参数进行传递), 时机 : 返回上一界面之前.
例如有两个视图控制器:
FirstViewController 和 SecondViewController
在这两个视图控制器中设置一个textField 和 label, 并且把SecondViewController的view上的textField上输入的text显示到FirstViewController的label上.
在SecondViewController.h文件中
#import <UIKit/UIKit.h>
// 代理传值 第一步 : 定义协议
@protocol SecondViewControllerDelegate <NSObject>
- (void)passValue:(NSString *)data;
@end
@interface SecondViewController : UIViewController
// 代理传值第二步 : 定义代理属性, 存储代理对象
@property (nonatomic, assign) id<SecondViewControllerDelegate> delegate;
@end
在FirstViewController.m文件中
#import "FirstViewController.h"
#import "SecondViewController.h"
// 代理传值第四步 : 服从协议.
@interface FirstViewController () <SecondViewControllerDelegate>
@end
@implementation FirstViewController
#pragma mark -- second view controller delegate
// 代理传值第五步 : 前一个界面实现协议中的方法
- (void)passValue:(NSString *)data {
((UILabel *)[self.view viewWithTag:200]).text = data;
}
- (void)viewDidLoad {
[super viewDidLoad];
/**
导航控制器的工作原理:
导航控制器以栈的形式管理视图控制器, 当进入下一个界面时, 该视图控制器入栈, 当返回上一界面时, 该视图控制器出栈, 入栈前, 视图控制器开辟空间, 出栈后, 视图控制器被系统回收, 屏幕永远显示的是导航控制器的栈顶元素.
*/
// 进入下一界面的按钮
[self setupButton];
// 设置TextField
[self setupTextField];
// 设置Label
[self setupLabel];
}
// 创建button
- (void)setupButton {
UIButton *pushBtn = [UIButton buttonWithType:UIButtonTypeSystem];
pushBtn.frame = CGRectMake(20, 100, 280, 40);
[pushBtn setTitle:@"进入下一个界面" forState:UIControlStateNormal];
pushBtn.backgroundColor = [UIColor blueColor];
[pushBtn addTarget:self action:@selector(handlePushBtn:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:pushBtn];
}
// 创建textField
- (void)setupTextField {
UITextField *textFiled = [[UITextField alloc] initWithFrame:CGRectMake(20, 230, 280, 40)];
textFiled.placeholder = @"显示到第二个界面上";
[self.view addSubview:textFiled];
textFiled.tag = 100;
textFiled.backgroundColor = [UIColor grayColor];
[textFiled release];
}
// 创建label
- (void)setupLabel {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 300, 280, 40)];
label.backgroundColor = [UIColor whiteColor];
label.layer.borderWidth = 2;
label.layer.cornerRadius = 5;
label.tag = 200;
[self.view addSubview:label];
[label release];
}
#pragma mark -- button action
- (void)handlePushBtn:(UIButton *)sender {
// 代理传值, 从后往前传
// 1. 创建的二个视图控制器
SecondViewController *secondVC = [[SecondViewController alloc] init];
// 代理传值 第三步 :给后一个界面指定代理对象
secondVC.delegate = self;
// 2. 通过导航控制push到下一个界面(视图控制器自带的navigationController 属性能够获取到管理当前视图控制器的导航控制器, 然后, 再通过导航控制器进行push)
[self.navigationController pushViewController:secondVC animated:YES]; // 该行代码表示进入下一个界面.
// 3. 释放
[secondVC release];
}
@end
在SecondViewController.m 文件中
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设置下一页面的按钮
[self setupPushButton];
// 设置TextField
[self setupTextField];
// 设置Label
[self setupLabel];
// 设置上一页面的按钮
[self setupPopButton];
}
// 创建button
- (void)setupButton {
UIButton *pushBtn = [UIButton buttonWithType:UIButtonTypeSystem];
pushBtn.frame = CGRectMake(20, 100, 280, 40);
[pushBtn setTitle:@"进入下一个界面" forState:UIControlStateNormal];
pushBtn.backgroundColor = [UIColor blueColor];
[pushBtn addTarget:self action:@selector(handlePushBtn:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:pushBtn];
}
// 创建textField
- (void)setupTextField {
UITextField *textFiled = [[UITextField alloc] initWithFrame:CGRectMake(20, 230, 280, 40)];
textFiled.placeholder = @"显示到第二个界面上";
[self.view addSubview:textFiled];
textFiled.tag = 100;
textFiled.backgroundColor = [UIColor grayColor];
[textFiled release];
}
// 创建label
- (void)setupLabel {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 300, 280, 40)];
label.backgroundColor = [UIColor whiteColor];
label.layer.borderWidth = 2;
label.layer.cornerRadius = 5;
label.tag = 200;
[self.view addSubview:label];
[label release];
}
#pragma mark -- button action
- (void)handlePopBtn:(UIButton *)sender {
// 代理传值第六步 : 让代理执行任务
// 安全处理, 判断代理是否实现了方法, 防止崩溃
if ([self.delegate respondsToSelector:@selector(passValue:)]) {
[self.delegate passValue:[(UITextField *)[self.view viewWithTag:200] text]];
}
// 1. 返回上一界面
[self.navigationController popViewControllerAnimated:YES];
}
- (void)dealloc {
[_data release];
[super dealloc];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end