iOS中Blocks的介绍
1. 什么是Blocks
Blocks是C语言的扩充功能。如果用一句话来概括就是:带有自动变量的匿名函数。
第一次看见Blocks的时候,感觉很类似C语言的函数指针,尤其是Block类型变量,更是有极强的相似度。但Blocks不是一个指针,而是一个不带名字的函数,它允许开发者在两个对象之间将任意的语句当作数据进行传递,同时它又能获得上下文的信息(闭包Closure),所以在一些场合使用Blocks很方便简洁。
2. Block语法
我们先来看一个例子吧。
^int(int count){return count++;}
这个Block非常简单,就是把计数器加一,但麻雀虽小,五脏俱全,语法上一个元素都没漏掉。首先是^符号(插入符号caret),然后依次是是返回值类型,参数列表,表达式。
^ int (int count) {return count++;}
caret 返回参数 参数列表 表达式
齐全的Block就是这些内容了,不同的Block的表达式的复杂程度各异,但元素就是这么多了。
不过很多时候我们会遇到没有返回参数,或者没有传入参数,甚至既没有传入参数也没有返回参数的情况。这个时候Block可以省略相关的内容,就是说相对应的那一块不用写了。比如:
没有返回参数,可能就会写成:^(int count){printf("count=%d", count);}
没有参数列表,可能会写成:^int{return 1;}
既没有返回参数也没有参数列表,可能就会写成:^{printf("Blocks Demo!\n")};
Block还可以申明变量,Block变量一样可以用typedef来定义成新的类型,这种做法下和函数指针真的非常非常类似,仅仅是将*换成了^。举个例子:
int (^blk)(int) = ^int (int count) {return count+;};
熟悉C语言的人对这个都会比较熟悉。这里有一个要说明,上面的赋值语句右侧可以省略掉返回类型(猜测是这部分信息编译器已经可以确定,所以不再是必须提供的了)。这样,上面的语句也可以写成;
int (^blk)(int) = ^(int count) {return count+;};
如果使用typedef,就可以更清晰一点:
typedef
int (^blk_t)(int);
blk_t blk = ^(int count) {return count+;};
3. 截获自动变量值
我们说Block是带自动变量的匿名函数,匿名函数现在已经知道了,下面就要看看“自动变量”了。Block可以访问在它之前申明的变量,但也有它特殊的地方,先看一个例子:
int main(int argc, const char * argv[])
{
int val = 1;
void (^blk)(void) = ^{printf("val=%d\n", val);}; val = 2;
blk();
return 0;
}
在这里,运行结果是val=1。请注意,虽然这个时候val的值已经变成了2,但Block里面仍然是1,也就是说,Block在定义时相当于对val这个变量照了张相,然后一直自己使用这张相片,不管val本身何去何从。
这个特性可以带来很大的便利(记下了定义时的上下文),有时是我们所需要的;但一不小心也很容易错,所以使用时需要注意。另外需要说明的是,Block里面不能改变val这个变量的值,如果你试图改变,编译器会报错,换句话说,Block里面,val就是只读的,而且值就是定义时的那个。
虽然记住上下文是个很棒的功能,但是有时我们需要外部上下文变化时,Block的内容也跟随改变或者要修改自动变量的值,这个就需要用到__block关键词了。继续上代码:
int main(int argc, const char * argv[])
{
__block int val = 1;
void (^blk)(void) = ^{printf("val=%d\n", val);}; val = 2;
blk();
return 0;
}
这段代码和上一段的区别仅仅是多了__block的声明,但运行结果就是val=2了,也就是说,Block能跟踪val的变化了。
这时,Block里面也可以改变val的值了,就是说,用了__block之后,val对于Block不再是只读的了,而是和自己定义的变量一样了。
在一个Block里面,往往两种变量都需要有,具体怎么使用,就看具体的情况了。
4. Block的使用
我总是觉得任何一种技术的出现总是用来解决某个问题的,也决定了在何种情况下使用该技术。Block应该如何使用呢?这是仁者见仁,智者见智的问题了,我接触最多的是在GCD里面。
个人的感觉这个东东主要用在回调里面,比如:网络连接成功后我应该把某个按钮激活之类的,Block使用起来简洁明快,如鱼得水。GCD实际上也是给出了系统的回调,所以就特别适合Block大显身手。
5. 其他
Block当然还有其他的一些内容,比如可以作为函数参数来传递,比如当自动变量是ObjC的对象时,虽然不能修改,但可以调用对象的方法,再比如,C语言的数组不能作为自动变量等等。但这些都不是Block主要的内容,最重要的还是灵活的使用。
iOS中Blocks的介绍的更多相关文章
- iOS中NSBundle的介绍
bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle,cocoa提供了类NSBund ...
- http相关概念在iOS中的使用介绍
http://www.cocoachina.com/ios/20160329/15773.html
- iOS 中Block以及Blocks的使用,闭包方法调用
OC: -(void)dataWithUrl:(NSString*)string AndId:(NSInteger)id returnName:(void(^)(NSString*name))back ...
- iOS开发UI篇—iPad开发中得modal介绍
iOS开发UI篇—iPad开发中得modal介绍 一.简单介绍 说明1: 在iPhone开发中,Modal是一种常见的切换控制器的方式 默认是从屏幕底部往上弹出,直到完全盖住后面的内容为止 说明2: ...
- ios中框架介绍
ios中框架介绍 参考博客: 参考文章:框架介绍 框架介绍 框架就是一个目录,一个目录包含了共享库,访问共享库里面的代码的头文件,和其他的图片和声音的资源文件.一个共享库定义的方法和函数可以被应用程序 ...
- ios中xib的使用介绍
ios中Xib的使用 ios中xib的使用 Nib files are the quintessential(典型的) resource type used to create iOS and Mac ...
- iOS中多线程原理与runloop介绍
一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...
- IOS中获取各种文件的路径介绍及方法
IOS中获取各种文件的目录路径的方法 技术交流新QQ群:414971585 iphone沙箱模型的有四个文件夹,分别是什么,永久数据存储一般放在什么位置,得到模拟器的路径的简单方式是什么. docum ...
- Swift - iOS中各种视图控制器(View Controller)的介绍
在iOS中,不同的视图控制器负责不同的功能,采用不同的风格向用户呈现信息.下面对各个视图控制器做个总结: 1,标准视图控制器 - View Controller 这个控制器只是用来呈现内容.通常会用来 ...
随机推荐
- sass颜色
1只定义一次颜色 {优点:可以给变量赋予不同的值: {缺点:变量名称更改与变量值混乱: 2变浅加深 /*颜色函数*/ .warning-box { background-color:lighten($ ...
- Struts2的Stack Context和ValueStack
1.提到Struts2的传值功能时,经常会见到Stack Context和ValueStack等概念,那么它们到底是什么,有什么作用呢. ValueStack(值栈):Struts2将OGNL上下文设 ...
- License制作
最近,部门的产品要做license,于是上网查了一些通用软件的License做法,拿过来学习一下. 一个老外写的,很好,几乎完全涵盖了软件License的制作流程 http://afewguyscod ...
- RDLC报表 在WinForm里运行出现 未能加载文件或程序集 Microsoft.ReportViewer.WinForms, Version=11.0.0.0 System.IO.FileNotFoundException
原文:RDLC报表 在WinForm里运行出现 未能加载文件或程序集microsoft.reportviewer.winforms 推荐以下方案二 做一下记录顺便帮助一下遇到问题的朋友. 做RDLC报 ...
- 再度分(tu)析(cao)Egret这个年轻人
写在最前 笔者用Egret来开发游戏已经有2年多之久了,从它出现到如今的3.2.x版本,经历了很多很多,也做了很多类型的游戏了,关键是踩了很多很多坑. 很多网友问我Egret有哪些优劣,我也只是说了一 ...
- 初识Java--线程同步(2)
本文讲述Java中的线程同步和生产者消费者问题,其中主要涉及线程同步和wait().notify()方法的用法. wait和notify方法只能用在线程同步中,wait和notify是object的方 ...
- linux 学习之七-部分ssh命令
ssh命令 /etc/init.d/sshd restart|start|stop 重启|开始|关闭SSH的服务 ssh IP地址 连接SSH Linux scp命令用于Linux之间复制文件和目 ...
- 重写系统中的UINavigationController返回按钮的事件
1.扩展UIviewController UIViewController+BackButtonHandler.h #import <UIKit/UIKit.h> @protocol Ba ...
- oracle10G之前介质下载地址【珍藏版】
今天在互联网搜了一下相关介质下载,自己记录一下. Oracle9i Database Release 2 Enterprise/Standard/Personal Edition for Window ...
- 关于用exec来执行存储过程中,参数带有引号的解决方法
比如:exec 存储过程名 要带有引号的参数 这样写的时候是传不进引号的,可以选定一种字符来表示引号,在存储过程中再进行转换: @test=replace(replace(@test,char(39) ...