#pragma mark - 反向传值
//主动方(第二个界面):1.创建协议及协议方法 2.设置一个代理属性 3.判断代理是否存在以及协议方法时候存在,然后再传值
//被动方:1.遵守协议 2.设置代理 3. 实现代理方法
@protocol ShowTextDelegate
@required
-(void)showText:(NSString *)text;
@optional
-(UIColor *)showTextOne:(NSString *)text;
@end
@interface SecodViewController : UIViewController
@property (nonatomic,assign)id
@end
//调用代理方法
//判断代理存在,且代理方法有响应
if (_delegate && [_delegate respondsToSelector:@selector(showText:)]) {
UIColor *color =[_delegate showTextOne:textField.text];
self.view.backgroundColor = color;
}
@interface RootViewController ()
//建立代理关系
svc.delegate = self;
//实现代理方法
-(UIColor *)showTextOne:(NSString *)text
{
// 找到显示文字的label
UILabel *label = (id)[self.view viewWithTag:10];
label.text = text;
return [UIColor greenColor];
}
//主动方
1.@property (nonatomic ,assign)id delegate;
2.[self.delegate setValue.btn.currentTitle forKey:@"viewCtrTitle"];
//被动方
1.@property (nonatomic,copy) NSString *viewCtrTitle;
2.svc.delegate = self;
3.self.navigationitem.title = viewCtrTitle;
@property (nonatomic,copy)void(^block)(NSString *text);
//2.SecodViewController要传递文字,它是需要声明block的一方
//3.SecodViewController它声明,它调用 (这样才能传过去一个数,才叫反向传值)
//4.声明一个属性,指向要调用的block
/*
1.驱动方声明一个block属性 驱动方调用block,执行block中得代码
2.被动方要具体实现block<驱动的block属性应该指向被动方实现的block>
*/
if (_block) {
_block(textField.text);
}
//1.实现显示文字的功能,也就是它需要完成block的实现部分 这是第一个控制器的内容
SecodViewController *svc = [[SecodViewController alloc]init];
UILabel *label = (id)[self.view viewWithTag:10];
void(^aBlock)(NSString *text) = ^(NSString *text){
label.text = text;
};
//声明的block指向实现的block
svc.block = aBlock;
#pragma mark - block的基本使用 只有调用block才会实现block中的代码
传入方声明block调用block,接收方实现block对传过来的值进行使用
#warining 1.声明block 2.调用block 3.实现block
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//1.block的声明
//声明一个名字为blockName的block变量
//-(void)funcName:(BOOL)value
void(^blockName)(BOOL value,NSString *str); (这句话blockName是名字,其余的是类型)
//2.给block赋值
blockName = ^(BOOL va1,NSString * str1){ (这是给block赋值)
NSLog(@"%d,%@",va1,str1);
};
//也可以把这一步和上一步合起来写,就是声明并且赋值
void(^blockName)(BOOL value,NSString *str) = ^(BOOL va1,NSString * str1){ (这是给block赋值)
NSLog(@"%d,%@",va1,str1);
};
blockName(YES,@"调用block"); (这是调用block)
//声明一个带返回值的block,并给它赋值
__unsafe_unretained RootViewController *rvc =self;
NSString *(^block2)(UIColor * color) =^(UIColor * colorValue){
rvc.view.backgroundColor = colorValue;
return@"用来返回的字符串";
};
NSString *str = block2([UIColor greenColor]);
NSLog(@"block返回的字符串====%@",str);
//3:block作为参数
void(^useBlock)(BOOL value) = ^(BOOL value)
{
if (value ==YES) {
NSLog(@"作为参数的block");
}
};
[self useAblock:useBlock];
/*
[self useAblock:^(BOOL value) {
if (value == YES) {
NSLog(@"作为参数的block");
}
}];
*/
-(void)useAblock:(void(^)(BOOL value))block
{
if (block) {
NSLog(@"用block了");
//如果作为参数的block存在,就调用block
block(YES);
}
}
//4.block作为返回值
void(^returnAblock)(BOOL value) = [self returnAblock];
if (returnAblock) {
//如果返回的block有值就调用block
// 调用block
returnAblock(YES);
}
}
//作为返回值
-(void(^)(BOOL value))returnAblock
{
return ^(BOOL value){
NSLog(@"作为返回值的block");
};
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self funcName:YES];
}
//函数的实现部分,不调用是不会执行函数中得代码的,调用才执行
-(void)funcName:(BOOL)value
{
NSLog(@"调用函数");
}
#pragma mark - block的本质
- 需要注意防止循环引用,使用__weak关键词修饰
void test5();
int main(int argc,const char * argv[])
{
test5();
return0;
}
int num = 10;
void test5()
{
void (^block)() = ^{
// block内部能够一直引用全局变量
NSLog(@"----num=%d", num);
};
num = 20;
block();
}
void test4()
{
staticint age = 10;
void (^block)() = ^{
// block内部能够一直引用被static修饰的变量
NSLog(@"----age=%d", age);
};
age = 20;
block();
}
void test3()
{
__blockint age = 10;
void (^block)() = ^{
// block内部能够一直引用被__block修饰的变量
NSLog(@"----age=%d", age);
};
age = 20;
block();
}
void test2()
{
int age =10;
void (^block)() = ^{
// 普通的局部变量,block内部只会引用它初始的值(block定义那一刻),不能跟踪它的改变
//因为block不知道这个变量什么时候被销毁,所以直接把变量的值放到那个位置,不管以后变量的死活了,但是全局变量,被static修饰的变量,被_block修饰的变量可以一直引用,就是可以跟踪变量的变化
NSLog(@"----age=%d", age);
};
age = 20;
block();
}
void test()
{
int age =10;
void (^block)() = ^{
// ----age=10
NSLog(@"----age=%d", age);
};
block();
}
#pragma mark - block 传值
//2.block
@property (nonatomic, copy)void(^block)(NSString *text);
//2.SecodViewController要传递文字,它是需要声明block的一方
//3.SecodViewController它声明,它调用 (这样才能传过去一个数,才叫反向传值)
//4.声明一个属性,指向要调用的block
/*
1.驱动方声明一个block属性 驱动方调用block,执行block中得代码
2.被动方要具体实现block<驱动的block属性应该指向被动方实现的block>
*/
if (_block) {
_block(textField.text);
}
//下面这代码在第一个控制器里面
//1.实现显示文字的功能,也就是它需要完成block的实现部分
SecodViewController *svc = [[SecodViewController alloc]init];
UILabel *label = (id)[self.view viewWithTag:10];
void(^aBlock)(NSString *text) = ^(NSString *text){
label.text = text;
};
//声明的block指向实现的block
svc.block = aBlock;
// 创建一个通知
//第一种:创建通知的方法
//A :携带对象
//1.通知的名字
//2. 通知携带的对象
//3.通知携带的信息
/*
NSNotification *notify = [[NSNotification alloc]initWithName:@"ShowText" object:textField userInfo:nil];
*/
// B:携带信息
//
// NSDictionary *infoDict = [NSDictionary dictionaryWithObject:textField.text forKey:@"text"];
// NSNotification *notify1 = [[NSNotification alloc]initWithName:@"showtext" object:nil userInfo:infoDict];
//获取通知中心
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
// [nc postNotification:notify];
// [nc postNotification:notify1];
//第二种,创建并发送一个携带对象的通知
[nc postNotificationName:@"ShowText" object:textField.text];
//第三种,通知中创建一个携带对象或携带信息的通知并发送
[nc postNotificationName:@"ShowText" object:textField.text userInfo:[NSDictionary dictionaryWithObjectsAndKeys:textField.text,@"text",nil]];
//获取通知中心
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(ShowFunc:) name:@"showtext" object:nil];
-(void)ShowFunc:(NSNotification *)notify
{
//获取通知携带的信息
NSDictionary *infoDict = notify.userInfo;
UILabel *label = (id)[self.view viewWithTag:10];
label.text = [infoDict objectForKey:@"text"];
}
-(void)dealloc
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self name:@"ShowText" object:nil];
//[nc removeObserver:self];移除所有通知
}
总结:通知中心发送通知,通知中心接受通知,通知中心移除观察者
(在下一个界面设置上一个界面的属性值)kvc的传值方法和正向传值的方法原理都是一样的
注意:下面的用单例和全局变量传值基本上不适用知道就好了
//(1.AppDelegate)
//保存输入的文字,保存到AppDelegate对象的属性
AppDelegate *del = [UIApplication sharedApplication].delegate;
del.text = textField.text;
//整个应用程序有一个单例对象UIApplication的对象,也只有一个代理,AppDelegate的对象也只有一个
AppDelegate *del = [UIApplication sharedApplication].delegate;
UILabel *label = (id)[self.view viewWithTag:10];
//读取单例属性存储的文字
label.text = del.text;
//(2.自定义一个单例)
//创建单例
//获取单例对象
SingleTon *single = [SingleTon shareSingleTon];
//用单例的属性保存输入的文字
single.text = textField.text;
//获取单例对象
SingleTon *single = [SingleTon shareSingleTon];
UILabel *label = (id)[self.view viewWithTag:10];
//读取单例对象的属性值
label.text = single.text;
//声明一个全局变量
NSString *text;
//用全局变量去保存输入的文字
text = textField.text;
//说明text在别的文件声明的
extern NSString *text;
UILabel *label = (id)[self.view viewWithTag:10];
label.text = text;