关于Objective-C的回调,最常见的应该是用 delegate
代理实现。不过代理的实现比起 Block
要更基础,就不介绍了,下面总结一下 Block
回调的实现。
就拿我昨天才写的博客为例: [iOS] 输入框高度随输入内容变化
在昨天的例子中,我的组件封装控件后,是通过代理实现返回行数的变化的。这次改用 Block
来实现。
Block
类型,用来代替原来的 @Protocol
typedef void(^getTextViewRows)(NSInteger lines);
interface
中声明参数为 Block
的实例方法 - (void)textViewRowsChangeTo:(getTextViewRows)block;
textViewRowsChangeTo:
的方法 - (void)textViewRowsChangeTo:(getTextViewRows)block {
block(lines);
}
唉,等等,我应该返回的行数是在 textViewDidChange:
运行时获得后才返回的啊,这样写还回调个什么鬼。。
所以我们需要声明一个 Block
变量,保存从外部传进来的 Block
的地址,然后当我们获取到改变的行数后,再从这个地址把正确的内容返回。
在第2步添加声明 Block
变量
@property (nonatomic, strong) getTextViewRows b_getRowsBlock;
- (void)textViewRowsChangeTo:(getTextViewRows)block;
修改第3步
- (void)textViewRowsChangeTo:(getTextViewRows)block {
_b_getRowsBlock = block;
}
然后在需要返回行数的时候,把行数作为参数传给 Block
- (void)textViewDidChange:(UITextView *)textView {
NSInteger numLines = textView.contentSize.height / textView.font.lineHeight;
if (numLines != rows) {
rows = numLines;
//发生换行
_b_getRowsBlock(rows);
}
......
}
最后,在外部调用前面的实例方法即可
B *b = [B new];
[b textViewRowsChangeTo:^(NSInteger lines) {
rowCount = lines;
[self remakeConstraint];
}];
最后,这又是一篇How to do的文章。说起来价值不算大。
但我觉得,想快速学一个新东西并且上手用起来,是需要从不断模仿别人写的代码做起的。
就像我第一次看代理,虽然了解大概实现过程,但用起来还是经常会出现忘写 XX.delegate = self
这看似微不足道的代码的,导致的结果就是调试程序的时候发现代理不起作用,然后排查业务逻辑,看手势事件有没有捕捉到…到最后才会想到排查语法错误。一个小错误导致我效率低下。(这种错误其实是对代理实现原理理解的不够造成的,但对于新手,理解需要时间,而要快速上项目就需要熟记这个实现流程,然后通过大量编码的过程去参悟原理。)
我想说的是,一般调试逻辑bug的时候很少会去想到语法错误,这就要求了我们平时写代码的时候要注意编程的细节,在学习的时候打好基础。有时候为了追求快速实现功能,可以不去深究,知道实现步骤就可以,比如说这个 Block
回调,这篇文章就可以作为一个模板,每次用的时候都按照这个步骤去做可以保证不出错,可以快速出效果。照着这个写多了,熟练了就自然不会犯低级的语法错误,这对提升效率很有帮助。这也是为什么我坚持记录How to do的文章的原因。
不过另外说起来,How to do的文章还有一个意义,那就是How to do都是有一个步骤顺序的,先干什么,再干什么。这个顺序就很有意义,它能提供一套解决问题的思路,也就是能看出这套语法的设计者是怎么去思考的。从设计者的思路去看语法就为我们后期深入学习理解相关知识提供了一条路子。当然了,具体能看到什么,学到什么还是看个人对编程的理解,也就是我所认为的编程心法。
好了,扯的有点偏,关于 Block
回调快速上手的方法就是这样了,熟记这个步骤(千万别死记,编码是灵活的),多去敲代码,慢慢就会产生诸如”为什么要写_b_getRowsBlock = block;”的疑问,当产生疑问时,那就说明你熟悉并开始思考语法了。一定要思考,不然注定是当一辈子的码农,而不是程序员。
关于 Block
的内容还有很多。由于平时 Block
用的的确少,所以关于这部分的资料我还需要一些时间去消化。后面我会尽量多写 Block
,感受不同场景下的使用。
最最后,我还记得几个月前我盯着代码发呆然后突然感叹一声:“原来这TM就是面向对象啊”的喜悦呢。