文章目录
- 属性传值(正向传值)
-
-
- 场景设置
- 第一步:创建两个ViewController
- [第二步:在 VCSecond 中声明属性](#第二步:在 VCSecond 中声明属性)
- 第三步:VCSecond中使用传过来的值
- 第四步:VCFirst中传值并跳转
-
- 代理传值 (反向传值)
-
-
- 场景设置
- [第一步:在 VCSecond.h 中定义协议](#第一步:在 VCSecond.h 中定义协议)
- [第二步:VCSecond.m 中调用代理方法](#第二步:VCSecond.m 中调用代理方法)
- [第三步:VCFirst 遵守协议并实现方法](#第三步:VCFirst 遵守协议并实现方法)
-
属性传值(正向传值)
正向传值 =从A界面→B界面传递数据
原理很简单:在B界面声明属性,A界面跳转前给属性赋值。
场景设置
A界面(
VCFirst)有一个输入框,用户输入文字后跳转到B界面(VCSecond),B界面显示该文字。
第一步:创建两个ViewController
VCFirst 和VCSecond
第二步:在 VCSecond 中声明属性
objc
// VCSecond.h
#import <UIKit/UIKit.h>
@interface VCSecond : UIViewController
// 声明一个属性,用来接收从A界面传过来的值
@property (nonatomic, copy) NSString *recievedText;
@end
关键点 :属性要声明在
.h文件中,这样 VCFirst 才能访问到它。
第三步:VCSecond中使用传过来的值
objc
// VCSecond.m
#import "VCSecond.h"
@interface VCSecond ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation VCSecond
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 创建label显示传过来的文字
self.label = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:self.label];
// 在这里使用传过来的值
self.label.text = self.recievedText;
}
@end
第四步:VCFirst中传值并跳转
objc
// VCFirst.m
#import "VCFirst.h"
#import "VCSecond.h"
@interface VCFirst ()
@property (nonatomic, strong) UITextField *textField;
@end
@implementation VCFirst
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 创建输入框
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 40)];
self.textField.borderStyle = UITextBorderStyleRoundedRect;
self.textField.placeholder = @"请输入内容";
[self.view addSubview:self.textField];
// 创建跳转按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 270, 200, 40);
[btn setTitle:@"跳转到第二页" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)btnClick {
// 1. 创建第二个控制器
VCSecond *vc = [[VCSecond alloc] init];
// 2. 核心:跳转前把值赋给B界面的属性
vc.recievedText = self.textField.text;
// 3. 跳转
[self.navigationController pushViewController:vc animated:YES];
}
@end
代理传值 (反向传值)
反向传递值 =从B界面→A界面传递数据(返回时传递值)
属性传值做不到反向传值,因为A跳转到B时,A已经处于等待了,B无法直接访问A。
代理模式三要素:
| 要素 | 比喻 |
|---|---|
| 协议(Protocol) | 规定"参与做某事" |
| 代理人(代表) | 真正做事的人(A界面) |
| 委托方 | 发出请求的人(B界面) |
场景设置
B界面有一个输入框,用户输入文字后点击返回,A界面的标签显示该文字。
第一步:在 VCSecond.h 中定义协议
objc
// VCSecond.h
#import <UIKit/UIKit.h>
// 第一步:定义协议
@protocol VCSecondDelegate <NSObject>
// 协议方法:B界面需要传值时调用这个方法
- (void)vcSecond:(id)vcSecond didSendText:(NSString *)text;
@end
@interface VCSecond : UIViewController
// 第二步:声明delegate属性
// weak避免循环引用!代理属性必须用weak
@property (nonatomic, weak) id<VCSecondDelegate> delegate;
@end
代理属性必须用
weak,避免A和B互相强引用导致内存泄漏。
第二步:VCSecond.m 中调用代理方法
objc
// VCSecond.m
#import "VCSecond.h"
@interface VCSecond ()
@property (nonatomic, strong) UITextField *textField;
@end
@implementation VCSecond
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
// 输入框
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 40)];
self.textField.borderStyle = UITextBorderStyleRoundedRect;
self.textField.placeholder = @"输入要传回的内容";
[self.view addSubview:self.textField];
// 返回按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 270, 200, 40);
[btn setTitle:@"返回并传值" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(backBtnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)backBtnClick {
// 核心:调用代理方法,把值传出去
// 判断代理是否实现了该方法(安全写法)
if ([self.delegate respondsToSelector:@selector(vcSecond:didSendText:)]) {
[self.delegate vcSecond:self didSendText:self.textField.text];
}
// 返回上一页
[self.navigationController popViewControllerAnimated:YES];
}
@end
第三步:VCFirst 遵守协议并实现方法
VCSecond 遵守协议
objc
// VCFirst.h
#import <UIKit/UIKit.h>
#import "VCSecond.h" // 导入,才能使用协议
// 遵守协议
@interface VCFirst : UIViewController <VCSecondDelegate>
@end
实现代理方法
objc
// VCFirst.m
#import "VCFirst.h"
@interface VCFirst ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation VCFirst
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 显示传回来的文字
self.label = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.label.text = @"等待传值...";
self.label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:self.label];
// 跳转按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 270, 200, 40);
[btn setTitle:@"去第二页" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)btnClick {
VCSecond *vc = [[VCSecond alloc] init];
// 核心:设置代理为self(我来负责处理回调)
vc.delegate = self;
[self.navigationController pushViewController:vc animated:YES];
}
// 实现协议方法,接收B传回来的值
- (void)vcSecond:(id)vcSecond didSendText:(NSString *)text {
self.label.text = text;
}
@end