前言
在开发中,在两个相邻的界面我们经常会进行逆向传值(反向传值)。
如:B界面是A界面的子界面,现在需求是将B界面的数据传递到A界面中并且显示数据。这时候我们已经不能够将B中的数据暴露在.h文件中了,否则会有很多的问题。
所以在日常的逆向传值中我们大致用到了以下三种方式进行反向传值
- Block传值
- 代理传值
- 通知传值
我这篇文章主要通过例子说一下前两种传值方式
优秀的Block文章:
https://blog.csdn.net/LVXIANGAN/article/details/43228845
https://www.cnblogs.com/jukaiit/p/5050982.html
1. Block传值
DetailViewController.h
#import <UIKit/UIKit.h>
typedef void(^textFildWithBlock)(NSString *String);
@interface DetailViewController : UIViewController
@property(nonatomic,copy)textFildWithBlock stringBlock ;
-(void)returnValue:(textFildWithBlock) stringBlock ;//这段可以不定义
@end
DetailViewController.m
#import "DetailViewController.h"
@interface DetailViewController ()
@property(nonatomic,strong)UITextField *textView ;
@property(nonatomic,strong)UIButton *btn;
@end
@implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem] ;
[btn setTitle:@"传值" forState:UIControlStateNormal] ;
btn.frame = CGRectMake(100, 200, 100, 22) ;
[btn addTarget:self action:@selector(playClick) forControlEvents:UIControlEventTouchUpInside] ;
[self.view addSubview:btn] ;
self.btn = btn ;
UITextField *textView = [[UITextField alloc]initWithFrame:CGRectMake(100, 300, 100, 44)] ;
textView.backgroundColor = [UIColor whiteColor] ;
[self.view addSubview:textView] ;
self.textView = textView ;
}
-(void)playClick{
if (self.stringBlock) {
self.stringBlock(self.textView.text) ;
}
[self.navigationController popViewControllerAnimated:YES] ;
}
-(void)returnValue:(textFildWithBlock) stringBlock{
self.stringBlock = stringBlock ;
}
ViewController.m
#import "ViewController.h"
#import "DetailViewController.h"
@interface ViewController ()
@property(nonatomic,strong)UIButton *btn ;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"blockDemo" ;
self.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem] ;
btn.frame = CGRectMake(100, 100, 100, 22) ;
[btn setTitle:@"点击跳转" forState:UIControlStateNormal] ;
[btn addTarget:self action:@selector(clickPush) forControlEvents:UIControlEventTouchUpInside] ;
[self.view addSubview:btn] ;
self.btn = btn ;
}
-(void)clickPush{
DetailViewController *deVc1 = [[DetailViewController alloc]init] ;
//1.通过block属性传值
deVc1.stringBlock = ^(NSString * _Nonnull String) {
[self.btn setTitle:String forState:UIControlStateNormal] ;
} ;
//2.通过声明的block方法传值
// [deVc1 returnValue:^(NSString * _Nonnull String) {
// [self.btn setTitle:String forState:UIControlStateNormal] ;
// }] ;
[self.navigationController pushViewController:deVc1 animated:YES] ;
}
@end
2. 代理传值
什么情况下使用代理
当上下级之间,下级要通知上级做事情,想传递数据给上级。通知上一级把数据展示出来。
写代理的过程:
里三步:
1.定义协议
2.定义代理属性
3.调用代理方法
外三步:
4.设置代理
5.遵守代理协议
6.实现代理方法
DetailViewController.h
#import <UIKit/UIKit.h>
//定义协议
@protocol DetailVCDelegate <NSObject>
-(void)popToFristVCValueString:(NSString *)value;
@end
@interface DetailViewController : UIViewController
//定义协议属性
@property(nonatomic,weak)id<DetailVCDelegate> delegate ;
@end
DetailViewController.m
#import "DetailViewController.h"
@interface DetailViewController ()
@property(nonatomic,strong)UIButton *button ;
@property(nonatomic,strong)UITextView *textView ;
@end
@implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"secendVC" ;
self.view.backgroundColor = [UIColor whiteColor ];
self.button = [UIButton buttonWithType:UIButtonTypeSystem] ;
self.button.frame = CGRectMake(100, 100, 100, 22) ;
[self.button setTitle:@"返回" forState:UIControlStateNormal] ;
[self.button addTarget:self action:@selector(clickPop) forControlEvents:UIControlEventTouchUpInside] ;
[self.view addSubview:self.button] ;
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(100, 200, 100, 50)] ;
textView.backgroundColor = [UIColor whiteColor] ;
textView.layer.borderColor = [UIColor blackColor].CGColor ;
textView.layer.borderWidth = 2 ;
[self.view addSubview: textView ] ;
self.textView = textView ;
}
-(void)clickPop{
[self.navigationController popViewControllerAnimated: YES] ;
//判断是否执行了代理方法
if ([self.delegate respondsToSelector:@selector(popToFristVCValueString:)]) {
// 加入if语句就是先判断在界面A中是否有changeBgColor这个方法,当有这个方法的时候,才进行代理传值。
//3.调用代理方法
[self.delegate popToFristVCValueString:self.textView.text] ;
}
}
@end
ViewController.m
#import "ViewController.h"
#import "DetailViewController.h"
@interface ViewController ()<DetailVCDelegate>
@property(nonatomic,strong)UIButton *button ;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"fristVC" ;
// self.view.backgroundColor = [UIColor whiteColor ];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem] ;
button.frame = CGRectMake(100, 100, 100, 22) ;
[button setTitle:@"点击" forState:UIControlStateNormal] ;
[button addTarget:self action:@selector(clickPush) forControlEvents:UIControlEventTouchUpInside] ;
[self.view addSubview:button] ;
self.button = button ;
}
-(void)clickPush{
DetailViewController *deVC = [[DetailViewController alloc]init] ;
deVC.delegate = self ;
[self.navigationController pushViewController:deVC animated:YES] ;
}
//实现代理方法
-(void)popToFristVCValueString:(NSString *)value{
[self.button setTitle:value forState:UIControlStateNormal] ;
}
@end
关于Block和代理传值的选择问题:
Block作为一个轻量级的代码块,在传递数据的时候具有很多的好处,但是如果数据过多的时候使用Block会使得代码显得很乱,所以这时候就要用代理进行传值。如果,已经用了代理传值了,那么尽量不要再用block了,除非block有其他用处。










网友评论