IOS中的Block与C++11中的lambda
ios中的block 可以说是一种函数指针,但更确切的讲,其实际上其应该算是object-c对C++11中lambda的支持或者说是一个语言上的变体,其实际内容是一样的,C++的lambda我已经有简介过,现在说下ios中的block
Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值。Block实体形式如下:
^(传入参数列){行为主体};
Block实体开头是“^”,接着是由小括号所包起来的参数列(比如 int a, int b, int c),return a*a;};
这是代表Block会回传输入值的平方值(int a 就是参数列, return a*a; 就是行为主体)。记得行为主体里最后要加“;”,因为是叙述,而整个{}最后也要加“;”,因为Block是物件实体。用法如下:
- int result = ^(int a){return a*a;}(5);
- NSLog(@"%d", result);
很奇怪吧?后面的小括号里面的5会被当成a的输入值,然后经由Block输出 5*5 = 25指定给result这个变量。
有没有简单一点的方法嗯?不然每次都写这么长?有。接下来介绍一个叫做Block Pointer的东西来简化我们的写法。
Block Pointer是这样定义的:
回传值(^名字)(参数列);
比如下面的例子:
- //声明一个square的Block Pointer,其所指向的Block有一个int输入和int输出
- int (^square)(int);
- //将Block实体指定给square
- square = ^(int a){ return a*a ; };
- //调用方法,感觉是是不是很像function的用法?
- int result = square(5);
- NSLog(@"%d", result);
是不是变的简单了?
也可以吧Block Pointer当成参数传递给一个function,比如:
- void myFunction(int (^mySquare)(int)); //function的定义,将Block作为参数
- int (^mySquare)(int) = ^(int a){return a*a;}; //定义一个mySquare的Block pointer变量
- myFunction(mySquare); //把mySquare作为myFunction的参数
上面的三行代码其实等价于下面这行代码:
- myFunction( ^int(int a){return a*a;} );
当其作为Object-C method的传入值的话,需要把类型写在变量前面,然后加上小括号。比如下面这种写法:
- -(void)objcMethod:(int(^)(int))square; //square参数的类型是int(^)(int)
存取变量
1、可以读取和Block pointer同一个Scope的变量值:
- {
- int outA = 8;
- int (^myPtr)(int) = ^(int a){ return outA + a;};
- //block里面可以读取同一类型的outA的值
- int result = myPtr(3); // result is 11
- NSLog(@"result=%d", result);
- }
下面来看一段很有意思的代码:
- {
- int outA = 8;
- int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值
- outA = 5; //在调用myPtr之前改变outA的值
- int result = myPtr(3); // result的值仍然是11,并不是8
- NSLog(@"result=%d", result);
- }
为什么result 的值仍然是11?而不是8呢?事实上,myPtr在其主体中用到的outA这个变量值的时候做了一个copy的动作,把outA的值copy下来。所以,之后outA即使换成了新的值,对于myPtr里面copy的值是没有影响的。
需要注意的是,这里copy的值是变量的值,如果它是一个记忆体的位置(地址),换句话说,就是这个变量是个指针的话,
它的值是可以在block里被改变的。如下例子:
- {
- NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
- int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
- NSLog(@"test array :%@", mutableArray);
- }
原本mutableArray的值是{@"one",@"two",@"three"},在block里面被更改mutableArray后,就变成{@"one", @"two"}了。
2、直接存取static类型的变量
- {
- static int outA = 8;
- int (^myPtr)(int) = ^(int a){return outA + a;};
- outA = 5;
- int result = myPtr(3); //result的值是8,因为outA是static类型的变量
- NSLog(@"result=%d", result);
- }
甚至可以直接在block里面修改outA的值,例如下面的写法:
- {
- static int outA = 8;
- int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
- int result = myPtr(3); //result的值是8,因为outA是static类型的变量
- NSLog(@"result=%d", result);
- }
3、Block Variable类型的变量
在某个变量前面如果加上修饰字“__block”的话(注意,block前面有两个下划线),这个变量就称作block variable。
那么在block里面就可以任意修改此变量的值,如下代码:
- {
- __block int num = 5;
- int (^myPtr)(int) = ^(int a){return num++;};
- int (^myPtr2)(int) = ^(int a){return num++;};
- int result = myPtr(0); //result的值为5,num的值为6
- result = myPtr2(0); //result的值为6,num的值为7
- NSLog(@"result=%d", result);
- }
因为myPtr和myPtr2都有用到num这个block variable,最终num的值为7.
IOS中的Block与C++11中的lambda的更多相关文章
- 在Windows 8.1及IE 11中如何使用HttpWatch
提示:HttpWatch现已更新至v9.1.8,HttpWatch v9.1及以上的版本现都已支持Windows 7,8,8.1和IE 11. 如果你的HttpWatch专业版授权秘钥允许进入vers ...
- iOS中为什么block用copy属性
1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...
- iOS 中使用Block时需要注意的retain circle
现在在ios中,block是越来越多了.自己在类中定义block对象时,需要注意block对象的使用方法,防止产生retain circle,导致内存泄露. 现在分析一下产生retain circle ...
- 理解ios 11中webview的视口
iOS 11在状态栏区域带来了一些新的,也许是不直观的行为,这对使用Apache Cordova或Ionic等工具的开发人员尤为重要.特别是,这种行为变化会影响任何基于Web的应用程序,这些应用程序在 ...
- iOS开发——高级篇——iOS中为什么block用copy属性
1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...
- iOS中使用block进行网络请求回调
iOS中使用block进行网络请求回调 HttpRequest.h // // HttpRequest.h // UseBlockCallBack // // Created by Michael o ...
- ios 中的block应用
在这个大冬天里默默敲着键盘,勿喷.今天学习swift过程中,学习到闭包,发现闭包和oc的block中有很多的相同之处,又重新学习了一下并且学习了一些高级点的用法,内容如下: 1.block格式说明:( ...
- iOS开发之OC与swift开发混编教程,代理的相互调用,block的实现。OC调用Swift中的代理, OC调用Swift中的Block 闭包
本文章将从两个方向分别介绍 OC 与 swift 混编 1. 第一个方向从 swift工程 中引入 oc类 1. 1 如何在swift的类中使用oc类 1.2 如何在swift中实现oc的代理 ...
- block使用小结、在arc中使用block、如何防止循环引用
引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...
随机推荐
- Linux进程管理
一.进程管理简介 进程是正在执行的程序或命令,每一个进程都是一个运行实体,都有自己的地址空间,并占用一定的系统资源. 进程管理的作用: 1.判断服务器的健康状态 2.查看系统中的所有进程 3.杀死进程 ...
- Ubuntu 16.04安装搜狗输入法
转载: http://www.it610.com/article/5319575.htm 打开firefox浏览器,输入网址www.baidu.com,打开后搜索搜狗拼音 linux进入到搜狗拼音li ...
- Java资源大全中文版(Awesome最新版)(转载)
原文地址:http://www.cnblogs.com/best/p/5876559.html 目录 业务流程管理套件 字节码操作 集群管理 代码分析 编译器生成工具 构建工具 外部配置工具 约束满足 ...
- Android Studio -修改LogCat的颜色
Android Studio -修改LogCat的颜色 author:Kang,Leo weibo:http://weibo.com/kangyi 效果图 设置 Preference->Edit ...
- iOS 开发之崩溃日志分析
1. (js 与webview 交互崩溃)-[CFRunLoopTimer release]: message sent to deallocated instance 0x62398f80 I've ...
- 14TH本周工作量及进度统计
14TH本周工作量及进度统计 本周psp: C(类别) C(内容) S(开始时间) ST(结束时间) I(中断时间) T(实际时间) 活动 本周会议 1 ...
- SCOI2009粉刷匠
Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个 ...
- nodejs的第三天学习笔记
一. CommonJS 规范 1.1nodejs 与 commonjs 之间的关系: 1)nodejs是一种服务器语言. a)开启服务的能力 b)文件读写的能力 服务器:就是一台安装了服务软件 2)c ...
- 实验三——for 语句及分支结构else-if
1.本节课学习到的知识点:在本次课中,我学习了for语句的使用,认识了for语句的执行流,明确了三种表达式的意义.以及最常用的实现多分支的else-if语句. 2.实验过程中遇到的问题及解决方法:在本 ...
- 屏蔽zencart logs文件夹下不断生成的日志文件
在根目錄下的logs文件夾中,經常生成一些錯誤文件類似myDEBUGxxxxx.log這樣的錯誤文件(而且這樣的錯誤文件由來并非網站出現什麽嚴重不可挽救的錯誤,大部分是一些未定義變量這樣的不起眼的小錯 ...