【Block回调】用于参数传递很不错的例子。
来源:互联网 发布:免费网络直播加速器 编辑:程序博客网 时间:2024/05/16 03:26
Block回调
我们在开发中常常用到函数回调,你可以用通知来代替回调,但是大多数时候回调还是比通知方便。
A 简单两个界面之间的传值
1 在A界面 一个 label 一个 button
2 点击button跳转到B界面
3 在B界面 的textField输入内容 ,单击按钮返回。并将值传递给A界面
4 A界面的label接受传递的值 并且显示。
我用的代码布局还需要在AppDelegate.h设置根控制器,我就不写了太简单了。这是其他的代码直接复制即可。
ViewController.h
#import "ViewController.h"
#import "SecondViewController.h"
@interfaceViewController ()
@property (nonatomic,strong)UILabel *nameLabel;
@end
@implementation ViewController
- (void)viewDidLoad
{
[superviewDidLoad];
//设置跳转按钮
UIButton *btn=[[UIButtonalloc]initWithFrame:CGRectMake(20,180, 130,50)];
[btn setTitle:@"跳转"forState:UIControlStateNormal];
[btn setTintColor:[UIColororangeColor]];
btn.backgroundColor=[UIColorblackColor];
[btn addTarget:selfaction:@selector(clickAction)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:btn];
self.nameLabel=[[UILabelalloc] initWithFrame:CGRectMake(20,80, 130,50)];
self.nameLabel.backgroundColor=[UIColororangeColor];
[self.viewaddSubview:self.nameLabel];
}
- (void)clickAction
{
SecondViewController *one=[[SecondViewControlleralloc]init];
[selfpresentViewController:one animated:YEScompletion:nil];
one.block=^(NSString *str){self.nameLabel.text=str; };
}
SecondViewController.h
#import <UIKit/UIKit.h>
@interface SecondViewController :UIViewController
typedef void(^ablock)(NSString *);
@property (nonatomic,copy)ablock block;
@end
SecondViewController.m
#import "SecondViewController.h"
@interfaceSecondViewController ()
@property (strong,nonatomic) UITextField *nameTextField;
@property (nonatomic,strong)UIButton *btn;
@end
@implementation SecondViewController
- (void)viewDidLoad
{
[superviewDidLoad];
//设置跳转按钮
UIButton *btn=[[UIButtonalloc]initWithFrame:CGRectMake(20,180, 130,50)];
[btn setTitle:@"跳转"forState:UIControlStateNormal];
[btn setTintColor:[UIColororangeColor]];
btn.backgroundColor=[UIColorblackColor];
[btn addTarget:selfaction:@selector(clickAction)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:btn];
self.btn=btn;
self.nameTextField=[[UITextFieldalloc] initWithFrame:CGRectMake(20,80, 120,40)];
self.nameTextField.layer.masksToBounds=YES;
self.nameTextField.layer.cornerRadius=20;
[self.viewaddSubview:self.nameTextField];
}
- (void)clickAction
{
if ([selfnotEmpty]) {
if (self.block) {
self.block(self.nameTextField.text);
//返回上一个界面。
[selfdismissViewControllerAnimated:YEScompletion:nil];
}
}else{
[self showAlert];
}
}
-(BOOL)notEmpty{
if ([self.nameTextField.textlength] == 0) {
returnNO;
}
returnYES;
}
-(void)showAlert{
UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"提示"message:@"请输入名字"delegate:selfcancelButtonTitle:@"Cancel"otherButtonTitles:@"Ok",nil];
[alert show];
}
@end
B 下面简单粗暴的来模拟一下回调使用的场景
1我现在在玩手机
2我手机突然没电了
3我让手机开始充电
4充电的时候我很无聊,要去看电视,等到手机充满电之后停止看电视,继续玩手机。
5我开始看电视
6手机充满电了,我听到手机响一下,我不看电视了,开始玩手机。
这个场景中哪里跟回调类似呢?哪里跟通知类似呢?其实我们可以认为手机充好电了通过回调的方式让我继续玩手机,也可以认为手机充好电了通知我可以继续玩手机,然后我主动继续玩手机。这里更像通知不像回调。但是换个思维想,如果手机本身没有回调机制,那他怎么能在恰好手机刚充满的时候响一下呢?
先不纠结这个问题,我们看看如果用block怎样来实现这样一个场景:
我们随便找个控制器写下以下代码:
- (void)viewDidLoad
{
[superviewDidLoad];
NSLog(@"我在玩手机");
NSLog(@"手机没电了");
[selfchargeMyIphone];
NSLog(@"我在看电视");
}
- (void)chargeMyIphone
{
//主线程休眠10秒
[NSThreadsleepForTimeInterval:10];
NSLog(@"电充好了");
}
注意 这里我用了NSTread sleep,这样会让我的主线程沉睡10秒钟,这个过程中我我真的可以一边看电视一边充电吗?
2015-09-10 15:54:37.719 38-demo-01[2046:113530]我在玩手机
2015-09-10 15:54:37.719 38-demo-01[2046:113530] 手机没电了
2015-09-10 15:54:47.720 38-demo-01[2046:113530] 电充好了
2015-09-10 15:54:47.721 38-demo-01[2046:113530] 我在看电视
所以我们应该让充电的线程和我看电视的线程错开执行!这里我们就不开新线程了,就让他10秒之后再执行吧。模拟下:
- (void)viewDidLoad {
[superviewDidLoad];
NSLog(@"我在玩手机");
NSLog(@"手机没电了");
[selfperformSelector:@selector(chargeMyIphone)withObject:nilafterDelay:10];
NSLog(@"我在看电视");
}
- (void)chargeMyIphone
{
NSLog(@"电充好了");
}
2015-09-10 15:53:06.723 38-demo-01[1985:112573] 我在玩手机
2015-09-10 15:53:06.724 38-demo-01[1985:112573] 手机没电了
2015-09-10 15:53:06.724 38-demo-01[1985:112573] 我在看电视
2015-09-10 15:53:16.724 38-demo-01[1985:112573] 电充好了
看起来没多大问题,但是我们还没写完我们的场景呢,我们想充好电之后继续玩手机?所以我们写在哪儿呢?
如果直接放在看电视后面:
NSLog(@"继续玩手机");
我们看看控制台:
2015-09-10 15:57:08.082 38-demo-01[2110:114748]我在玩手机
2015-09-10 15:57:08.083 38-demo-01[2110:114748]手机没电了
2015-09-10 15:57:08.083 38-demo-01[2110:114748]继续玩手机
2015-09-10 15:57:08.083 38-demo-01[2110:114748] 我在看电视
2015-09-10 15:57:18.083 38-demo-01[2110:114748] 电充好了
呵呵!电都没充好,你就直接继续玩了?所以这里应该是电充好以后我们再继续玩手机?
那么该怎么做?我们可以写进充电函数里吗?
- (void)chargeMyIphone
{
NSLog(@"电充好了");
NSLog(@"继续玩手机");
}
2015-09-10 15:59:34.257 38-demo-01[2199:116281]我在玩手机
2015-09-10 15:59:34.258 38-demo-01[2199:116281]手机没电了
2015-09-10 15:59:34.258 38-demo-01[2199:116281]我在看电视
2015-09-10 15:59:44.258 38-demo-01[2199:116281]电充好了
2015-09-10 15:59:44.258 38-demo-01[2199:116281]继续玩手机
看起来没多大问题,但是我们想想看,我们把 继续玩手机写在充电 函数的最后,
如果每次冲完电都继续玩手机,这个没什么问题,但是如果每次冲完电不总是玩手机
怎么办呢?如果逛街呢?这样的话,这样写就不对了,我们想让充电函数最后执行的那一行
是可变化的。有很多方式可以做到,但是这里最好的做法肯定是追加一个block替换掉我们写死的那句代码。
也就是在充电前已经安排好一个充电计划,今天充电完继续玩手机,明天改成逛街。
那么每次调用的还是那个充电函数,只是传入的参数不一样而已。
明白这一点就知道block的最终奥义了。改造下这个函数,为它加个包含代码的参数。
-(void)chargeMyIphone:(void(^)(void))finishBlock
{
NSLog(@"电充好了");
finishBlock();
}
这个追加的参数就是我们的block,
第一个void表示此block无返回值 ^ 为block type的标志第二个void表示这个block无参数,finishBlock就是它的名字。
无参数无返回值类型的匿名函数
就是我们最简单的block了,他非常方便我们回调。
因为没有返回值,没有参数,就相当于只有内部的可执行代码。
而我们讲一个固定的事件用一段代码作为参数传进来,并且一名字()形式来触发它,
那么这个函数的结尾就不会总是玩手机了,可以是任何事情!
- (void)viewDidLoad {
[superviewDidLoad];
NSLog(@"我在玩手机");
NSLog(@"手机没电了”);
[self chargeMyIphone:^{ NSLog(@"出去逛街 "); }];
NSLog(@"我在看电视");
}
-(void)chargeMyIphone:(void(^)(void))finishBlock
{
double delayInSeconds=10.0;
dispatch_time_t poptime=dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds *NSEC_PER_SEC));
dispatch_after(poptime,dispatch_get_main_queue(), ^(void){
NSLog(@"电充好了");
finishBlock();
});
}
2015-09-10 16:17:45.872 38-demo-01[2380:124074]我在玩手机
2015-09-10 16:17:45.873 38-demo-01[2380:124074]手机没电了
2015-09-10 16:17:45.873 38-demo-01[2380:124074]我在看电视
2015-09-10 16:17:56.868 38-demo-01[2380:124074]电充好了
2015-09-10 16:17:56.869 38-demo-01[2380:124074]出去逛街
现在代码的结果非常清晰
充电完成之后 我要去逛街
充电内不需要消耗10秒
充电的充实我可以看电视
充电完成之后 回头来触发我block中设置的出去逛街
- 【Block回调】用于参数传递很不错的例子。
- CMD 很不错的例子
- 一个用于传递可变参数的宏
- 关于参数传递的例子
- 指针传递参数的例子
- 一个很不错的XML Schema例子
- html向flash传递参数的例子
- JSP传递中文参数的例子
- HTML传递参数的方法和例子
- Block学习-关于Block是如何实现的,以及block中参数传递
- 一个很不错的jfreechar的入门例子
- 先看一下 NSArray 是怎么传递 block 参数的
- java.NIO网络编程很不错的一个例子
- JVM调优参数汇总啊!!!!总结的很不错。
- Java函数参数传递例子
- JavaScript 模式对话框实现及参数传递的简单例子
- javascript 动态绑定函数的参数传递例子
- com 传递参数与utf8的文字转换例子
- C/C++创建二维数组/指针数组
- C++map的用法
- C语言的整型溢出问题
- 设置 SeekBar宽度全屏
- LBP简介
- 【Block回调】用于参数传递很不错的例子。
- 易改1Checker 英文写作软件
- hdu 1151 Air Raid 【DAG最小路径覆盖】
- Asp.Net 小型网站的制作(二),涵盖了asp.net里面所有的基础知识
- g++: command not found的解决
- Ubuntu中定时
- 盘点一些唯美复古惊艳的古风句子
- 设置Intel 82579LM 抓Vlan tag报文
- UIday1301:block复习