初识Block的时候,总觉得其很可怕,因为看不懂其运行原理,所以用起来总是觉得不安全。关于Block的语法,等我把手里的资料全部看完,整理好再发出来。这次先看看用Block怎么实现回调。

新博客:wossoneri.com

关于Objective-C的回调,最常见的应该是用delegate代理实现。不过代理的实现比起Block要更基础,就不介绍了,下面总结一下Block回调的实现。

就拿我昨天才写的博客为例:[iOS] 输入框高度随输入内容变化

在昨天的例子中,我的组件封装控件后,是通过代理实现返回行数的变化的。这次改用Block来实现。

  1. 定义一个Block类型,用来代替原来的@Protocol
typedef void(^getTextViewRows)(NSInteger lines);
  1. interface中声明参数为Block的实例方法
- (void)textViewRowsChangeTo:(getTextViewRows)block;
  1. 实现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就是面向对象啊”的喜悦呢。(不是不懂,而是有了新的理解)

[Objective-C] Block实现回调和简单的学习思考的更多相关文章

  1. block学习二:使用Block替代回调

    使用Block替代回调,分为三步进行:

  2. 【转】JS回调函数--简单易懂有实例

    JS回调函数--简单易懂有实例 初学js的时候,被回调函数搞得很晕,现在回过头来总结一下什么是回调函数. 我们先来看看回调的英文定义:A callback is a function that is ...

  3. TestNG简单的学习-TestNG运行

    转载:http://topmanopensource.iteye.com/blog/1983735 TestNG简单的学习-TestNG运行 文档来自官方地址: http://testng.org/d ...

  4. Linux简单编程学习心得

    在Linux环境下简单编程学习心得 linux编程过程 在上周的<信息安全设计基础>的课程学习中学习到了在虚拟的linux环境下简单的编程.学习过程中接触到了vim.gcc和gcd在实验楼 ...

  5. 20145217《网络对抗》 MAL_简单后门学习总结

    20145217<网络对抗> MAL_简单后门学习总结 实践内容: 1.netcat的应用 2.socat的应用 3.meterpreter的应用 知识点学习总结 后门程序一般是指那些绕过 ...

  6. 【转】block一点也不神秘————如何利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...

  7. [置顶] block一点也不神秘————如何利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...

  8. 如何结合场景利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...

  9. block一点也不神秘————如何利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...

随机推荐

  1. (转) 面向对象设计原则(二):开放-封闭原则(OCP)

    原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...

  2. (转)Python3 模块3之 Urllib之 urllib.parse、urllib.robotparser

    原文:https://blog.csdn.net/qq_36148847/article/details/79153738 https://blog.csdn.net/zly412934578/art ...

  3. 牛客网Java刷题知识点float数据在内存中是怎么存储的

    不多说,直接上干货! float类型数字在计算机中用4个字节存储. 遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e (1)底数部分 使用二进制数来表示此浮点数的实际值 (2)指 ...

  4. 修改Hosts文件提示没有权限怎么办

    解决办法:给host文件赋予权限 1.打开电脑C盘,在目录C:\Windows\System32\drivers\etc 下找到hosts文件 2.右键hosts文件,选择属性 3.点击hosts属性 ...

  5. ES6基础教程一 学习笔记

    一.变量的声明 1.var 声明全局变量 在ES6中var用来声明全局变量. 2.let 声明局部变量 3.const 声明常量 二.变量的解构赋值 //1.数组赋值 let [a,b,c]=[1,2 ...

  6. 在自己网站中引入CU3ER/Flash 3D幻灯片效果和照片画框

    要求 必备知识 本文要求基本了解 JAVASCRIPT 和 XML基础语法知识. 运行环境 支持Flash Player的浏览器/Flash Player11及以上 演示地址 演示地址 下载地址   ...

  7. sql的存储过程实例--循环动态创建表

    创建一个存储过程,动态添加100张track表表名track_0 ~~ track_99注:sql的拼接只能用 CONCAT()函数 -- 创建一个存储过程 CREATE PROCEDURE crea ...

  8. php里use关键字与class_alias的作用域区别

    use可以用在命名空间下,也可以不用再命名空间下,他在两者中的作用是一致的,都是在编译的时候执行,不真正的加载类,因为是编译的时候执行,所以只能在全局环境使用,及不能使用在方法内部,条件判断内部. 引 ...

  9. Java NIO系列教程(五) 通道之间的数据传输

    在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...

  10. 记一次Java AES 加解密 对应C# AES加解密 的一波三折

    最近在跟三方对接 对方采用AES加解密 作为一个资深neter Ctrl CV 是我最大的优点 所以我义正言辞的问他们要了demo java demo代码: public class EncryptD ...