格而知之15:我所理解的Block(1)
1、Block 本质上是一个struct结构体,在这个结构体中,最重要的成员是一个函数(当然除函数外还有其他重要的成员)。
2、在开始解析Block之前,首先来回顾一下Block的格式。Block相关的格式有2个:
(1)、Block对象的格式;
(2)、Block变量的格式;
3、对于Block对象,它有几种常见的格式:
(1)、一个完整的Block对象的格式如下:
比如这个Block对象:
可以发现,完整的Block对象和函数的定义非常相似,比如这个函数:
两者之间的区别仅仅是:Block对象多了一个“^”符号,并且不需要像函数一样指定函数名;
(2)、在完整的格式中有一些项目是可以省略的,比如“返回值类型”。不管Block对象是否有返回值,这个项目都是可以省略的,省略之后,只要表达式中有return语句就会自动使用该返回值的类型,如果没有return语句就会使用void类型。
在这种情况下,Block对象的格式就变成了:
所以上文(1)中的Block对象可以写成这样:
(3)、除此之外,如果Block对象不需要参数的话,那么“参数列表”这个项目也是可以省略的,这时候Block对象的格式就变成了:
比如这样的一个Block对象:
4、定义了Block对象之后,还要定义Block变量来持有它,才能更方便地使用Block对象。回顾一下3(1)的函数:
对于这种函数,可以声明这样一个函数指针类型变量来使用它:
这时使用*funcPtr的就相当于在使用func函数了。
同样的,对于3(1)中的Block对象,也可以声明这么一个Block变量:
这时使用block()的时候就相当于在使用这个Block对象了。
对比函数指针和Block变量的声明,可以发现两者也是非常相似的,区别仅仅是将*号换成^号。
5、如果要将Block变量当做参数来传递的话,每次使用都完整地定义它显然是很麻烦的事。比如想要在一个函数里使用Block变量类型的参数,完整的定义方式应该是这样的:
这显然是很繁琐的,这时候就可以通过typedef来简化变量:
那么这个函数就可以定义成:
这时就可以非常方便地使用Block变量了。
6、回顾完Block 相关的格式,接下来开始来讨论Block的实现。
在前文提到过,Block最重要的组成部分是一个函数,这也就意味着,大部分Block能实现的功能,其实使用函数也可以实现的。接下来就先来试一试要如何在不使用Block的情况下实现Block的功能。
思考这么一个问题:假设有两个按钮button1和button2,要求实现以下功能:
(1)、按钮有编号;
(2)、编号可修改;
(3)、点击按钮输出自己的编号。
7、首先简单的方法可以通过使用两个函数来实现:
两个函数分别对应两个按钮的点击,调用函数时把按钮的编号作为参数传进去,便能打印出对应编号。
看起来似乎能满足功能了,但是这种方法的问题也是很明显的:按钮并不持有自己的编号,需要调用函数的时候才将编号传进去。
这种方法显然还不够完善。
8、根据面向对象的思考方式,通过将按钮抽象成类并把编号定义成按钮类的实例变量是可以实现这个功能的。但是这里只想要使用普通C语言来实现,那么可以这么处理,把每个按钮的编号定义成全局变量来进行保存,修改的代码如下:
这样按钮就“持有”了编号,实现了问题的3个要求。
9、回过头来看一看问题,如果要使用Block来实现这3个要求的话,代码会是这样的:
这段代码所实现的功能,和8的代码所实现的功能其实就是一样的了。
10、事实上,这两段代码几乎就是等价的了,8的代码几乎就是9的代码转换成普通C语言后的样子(注意“几乎”这个字眼,实际上5的代码转换成普通C语言后与4的代码还是有不少差别的)。
而对于问题中所提的3个要求,其实就是Block的3个主要功能点:
(1)、能截获变量;
(2)、能截获可变的变量;
(3)、回调。
格而知之15:我所理解的Block(1)的更多相关文章
- 格而知之3:Core Data的基本使用
最近准备做一个随手笔记类的app给自己用,考虑到从未使用过Core Data,就决定用Core Data来做数据存储.在网上参考了一些Core Data的资料后,用一天的时间写了这个demo,主要测试 ...
- PHP程序员应该知道的15个库
最几年,PHP已经成为最受欢迎的一种有效服务器端编程语言.据2013年发布的一份调查报告显示,PHP语言已经被安装在全球超过2.4亿个网站以及210万台Web服务器之上.PHP代表超文本预处理器,它主 ...
- 格而知之16:我所理解的Block(2)
11.那么Block到底是怎么实现的呢?试一试通过将Block 的代码转换成普通C语言代码来查看它的实现过程. 要将OC代码转换成C语言代码,可以使用clang编译的一个命令: 通过这个命令能把指定文 ...
- 格而知之8:我所理解的Runtime(3)
关联对象 14.使用Category对类进行拓展的时候,只能添加方法,而不适合添加属性(可以添加属性,也可以正常使用get方法和set方法,只是不会自动生成以下划线开头命名的成员变量). 可以通过关联 ...
- 格而知之6:我所理解的Runtime(1)
基本简介 1.根据官方文档,OC有一个特性:它会尽可能把一些决定从编译时和链接时推迟到运行时才处理,所以这门语言需要的就不只是一个编译器,它还需要一个runtime系统来处理那些已经被编译过的代码. ...
- 格而知之16:我所理解的Block(3)
23.在前文中的例子中,Block结构体里的isa指针还没有详细讲解,这个指针都被置向了_NSConcreteStackBlock,它标识了Block的类型. 其实除了_NSConcreteStack ...
- 格而知之7:我所理解的Runtime(2)
消息发送(Messaging) 8.以上便是runtime相关的一些数据结构,接下来我们回看一开始的疑问: objc_msgSend()函数在执行的过程中是如何找到对应的类,找到对应的方法实现的呢? ...
- 格而知之5:我所理解的Run Loop
1.什么是Run Loop? (1).Run Loop是线程的一项基础配备,它的主要作用是来让某一条线程在有任务的时候工作.没有任务的时候休眠. (2).线程和 Run Loop 之间的关系是一一对应 ...
- 每个php程序员都应该知道的15个最佳PHP库
PHP是一种功能强大的web站点脚本语言,通过PHP,web网站开发者可以更容易地创建动态的引人入胜的web页面.开发人员可以使用PHP代码与一些网站模板和框架来提升功能和特性.然而,编写PHP代码是 ...
随机推荐
- HTML浅识
HTML相关======= ## 认识网页 *web标准(w3c三种标准):结构标准 -->html 表现标准 -->css 行为标准 -->js **浏览器和服务器:浏览器发送报文 ...
- matlab遗传算法
function [xv,fv] = myGA(fitness, a, b, NP, NG, Pc, Pm, eps) % 用遗传算法求解一维无约束优化问题 % % 待优化的目标函数 fitness ...
- angularjs基本执行流程
近期温习了下angularjs执行流程,备记下.以便查看. 主要的执行流程例如以下: 1.用户请求应用起始页. 2.用户的浏览器向server发起一次HTTP连接,然后载入index.html页面,这 ...
- Salt安装
salt-master安装 [salt-master]# yum install salt-master 或者 curl -L http://bootstrap.saltstack.org | sud ...
- LoadRunner录制回放脚本RecContentType=application/json报错
今天做一个新项目,项目系统的框架是用SSH,特意查看了一下项目源码,用的ajax提交比较多,主要的问题是该系统对IE(8~10)浏览器都不兼容,无法进行录制. 是问题,总有解决的办法! 我本机为Loa ...
- Android企业级程序完全退出的解决方案
一.问题描述 在平常开发的过程中可以发现,很多开发者对于程序的退出都没有去认真的解决.一般要么是一个简单的finish(只是退出当前的activity),要么是其他的方法,比如: 1.第一种方法:首先 ...
- puppet 4.4 System Requirements
puppet是linux下自动部署管理工具,有apply,agent/server两种模式,安装后默认为agent/server模式. apply模式下,每台机器均有自己的catalog文件,如果需要 ...
- Mysql常用命令记录
-- 导出数据库: mysqldump -u user_name -p database_name > import_file.sql -- 执行脚本 source database.sql
- hdu find the safest road
算法:多源最短路(floyd) 题意:每条通路有一个安全系数,求始点到终点的最大的安全系数并输出,如果没有输出What a pity! c++超时啊 Problem Description XX星球有 ...
- mysql 8小时空闲后连接失效的解决
查了一下发现应用程序和mysql数据库建立连接,如果超过8小时应用程序不去访问数据库,数据库就断掉连接 .这时再次访问就会抛出异常. 关于mysql自动断开的问题研究结果如下, 1.c3p0.Hika ...