block
不使用__block修饰:
int num = ;
self.myBlock = ^(){
NSLog(@"block num == %d",num);
}; num = ;
self.myBlock();
NSLog(@"last num == %d",num); // 输入结果:
// 2016-09-13 13:13:15.362 block2[7543:562614] block num == 1
// 2016-09-13 13:13:15.363 block2[7543:562614] last num == 2
num 使用__block修饰后:
__block int num = ;
self.myBlock = ^(){
NSLog(@"block num == %d",num);
}; num = ;
self.myBlock();
NSLog(@"last num == %d",num); // 输出结果:
// 2016-09-13 13:14:20.964 block2[7574:570584] block num == 2
// 2016-09-13 13:14:20.964 block2[7574:570584] last num == 2
如果不用__block修饰变量,在block内强行修改变量会报错:

增加__block后,可以在block内部修改num:
__block int num = ;
self.myBlock = ^(){
num = ;
NSLog(@"block num == %d",num);
}; num = ;
self.myBlock();
NSLog(@"last num == %d",num); // 输出结果:
// 2016-09-13 13:16:44.961 block2[7632:585368] block num == 3
// 2016-09-13 13:16:44.962 block2[7632:585368] last num == 3
block调用完后再修改num:
__block int num = ;
self.myBlock = ^(){
num = ;
NSLog(@"block num == %d",num);
}; self.myBlock();
num = ;
NSLog(@"last num == %d",num);
// 输出结果:
// 2016-09-13 13:18:38.332 block2[7681:599563] block num == 3
// 2016-09-13 13:18:38.333 block2[7681:599563] last num == 2
block对对象类型的使用和对基本数据类型的使用一样:
不用__block修饰:
NSString *str = @"";
self.myBlock = ^(){
NSLog(@"block str == %@",str);
};
str = @"";
self.myBlock();
NSLog(@"last str == %@",str); // 输出结果:
// 2016-09-13 13:23:03.091 block2[7815:628689] block str == 1
// 2016-09-13 13:23:03.092 block2[7815:628689] last str == 2
使用__block修饰:
__block NSString *str = @"";
self.myBlock = ^(){
NSLog(@"block str == %@",str);
};
str = @"";
self.myBlock();
NSLog(@"last str == %@",str); // 输出结果:
// 2016-09-13 13:25:17.199 block2[7867:638529] block str == 2
// 2016-09-13 13:25:17.199 block2[7867:638529] last str == 2
block内部修改对象:
__block NSString *str = @"";
self.myBlock = ^(){
str = @"";
NSLog(@"block str == %@",str);
};
str = @"";
self.myBlock();
NSLog(@"last str == %@",str); // 输出结果:
// 2016-09-13 13:27:49.440 block2[7937:651966] block str == 3
// 2016-09-13 13:27:49.441 block2[7937:651966] last str == 3
block调用完后再修改对象:
__block NSString *str = @"";
self.myBlock = ^(){
str = @"";
NSLog(@"block str == %@",str);
};
self.myBlock();
str = @"";
NSLog(@"last str == %@",str); // 输出结果:
// 2016-09-13 13:29:03.705 block2[7973:660957] block str == 3
// 2016-09-13 13:29:03.705 block2[7973:660957] last str == 2
总结:
__block的使用:
block对基本数据类型和对象类型的使用注意是一样的。即:
无论是基本数据类型还是对象类型,如果想在block内部改变外面变量的值,必须用__block修饰;如果外面的值改变也要影响block内部值,也必须用__block修饰。(与block外面的变量的值保持同步)
即如果想内部改变影响外部或者外部改变影响内部,那么变量必须用__block修饰
如果不加__block修饰,那么block会捕获变量的值,在之后不受外面变量的改变而改变;并且也不能在block内部修改变量的值
如果想在block内部修改变量的值,必须用__block修饰
block循环引用:
伴随着block能够捕获变量的能力的一个问题就是, 循环引用, 在ARC中, 只要不是用到纯C语言的库,管理内存的工作都不需要我们完成, 但是循环引用却是我们需要解决的, 最常见的就是当block捕获的变量是一个对象的属性(方法)的时候, 也就是会捕获到self, 那么这个时候就可能会造成循环引用(block属性应该被标记为copy), 解决方法也很简单, 使用一个对self弱引用的指针即可, 这个写法就很多了, 笔者习惯的写法是: __weak typeof(self) weakSelf = self;, 那么在block中使用weakSelf替代self调用相关的属性或者方法, 就不会造成循环引用
weakSelf和strongSelf:
使用weakSelf能够解决block捕获self造成的循环引用的内存泄漏问题, 但是带来的另一个问题就是, 特别是在多线程中,可能在block中代码正在执行的时候, self被销毁了, 因为使用weakSelf捕获到的是self的弱引用, 那么后续的代码就不能够继续执行了, 这个时候为了保证在这个block中self即使被销毁block里面的代码也能正常执行, 我们需要的另一个操作就是, 将weakSelf强引用一次, 让他的引用计数加1, 就能处理这个问题, 就是Apple在wwdc中提到的weak-strong-dance, 笔者习惯的书写方式是: __strong typeof(self) strongSelf = weakSelf;,,, 当然这个必须要明白的是, 这个block里面的strongSelf能够保证里面代码执行完毕的前提是程序能够执行到block, 如果在执行block之前self已经被销毁了, 那么这个block肯定是不会被调用的(block的引用计数已经为0).
block的更多相关文章
- Objective-C中block的底层原理
先出2个考题: 1. 上面打印的是几,captureNum2 出去作用域后是否被销毁?为什么? 同样类型的题目: 问:打印的数字为多少? 有人会回答:mutArray是captureObject方法的 ...
- iOS 键盘添加完成按钮,delegate和block回调
这个是一个比较初级一点的文章,新人可以看看.当然实现这个需求的时候自己也有一点收获,记下来吧. 前两天产品要求在工程的所有数字键盘弹出时,上面带一个小帽子,上面安装一个“完成”按钮,这个完成按钮也没有 ...
- python中IndentationError: expected an indented block错误的解决方法
IndentationError: expected an indented block 翻译为IndentationError:预期的缩进块 解决方法:有冒号的下一行要缩进,该缩进就缩进
- JDBC Tutorials: Commit or Rollback transaction in finally block
http://skeletoncoder.blogspot.com/2006/10/jdbc-tutorials-commit-or-rollback.html JDBC Tutorials: Com ...
- 嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比
C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(i ...
- 嵌入式&iOS:回调函数(C)与block(OC)回调对比
学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...
- Block解析(iOS)
1. 操作系统中的栈和堆 我们先来看看一个由C/C++/OBJC编译的程序占用内存分布的结构: 栈区(stack):由系统自动分配,一般存放函数参数值.局部变量的值等.由编译器自动创建与释放.其操作方 ...
- CSS学习笔记——包含块 containing block
以下内容翻译自CSS 2.1官方文档.网址:https://www.w3.org/TR/CSS2/visudet.html#strut 有时,一个元素的盒子的位置和尺寸根据一个确定的矩形计算,这个确定 ...
- 用block做事件回调来简化代码,提高开发效率
我们在自定义view的时候,通常要考虑view的封装复用,所以如何把view的事件回调给Controller就是个需要好好考虑的问题, 一般来说,可选的方式主要有target-action和de ...
- 关于多个block问题
在某个添加文本的页面中,leftbarbutton是删除(直接将数组中的这个string删除),rightbarbutton是完成,分别对应两个block,完成的block是一开始写的,写到了view ...
随机推荐
- Inter1-关于i++和++i
Q:关于i++和++i计算以下公式的结果 ```public static void main(String[] args) { int i = 1; System.out.println(" ...
- Struts2入门(二)——配置拦截器
一.前言 之前便了解过,Struts 2的核心控制器是一个Filter过滤器,负责拦截所有的用户请求,当用户请求发送过来时,会去检测struts.xml是否存在这个action,如果存在,服务器便会自 ...
- MongoDB学习笔记(一) MongoDB介绍及安装(摘)
MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mongo使用C++开发.Mongo的官方网 ...
- [deviceone开发]-心形点赞动画示例
一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值.二.效 ...
- webpack 使用优化指南
前言 本文不是webpack入门文章,如果对webpack还不了解,请前往题叶的Webpack入门,或者阮老师的Webpack-Demos. 为什么要使用Webpack 与react一类模块化开发的框 ...
- 整理分享原生态mac AndroidStudio的快捷键
使用AndroidStudio开发半年了,一路爬坑至今,刚由Windows转mac一个星期.通过查些资料和自己摸索,记录一些常用的快捷键,犹豫个人不喜欢改快捷键,所以都是原生的.特此分享给大家!欢迎补 ...
- git分布式版本控制玩法
git分布式版本控制玩法 Git distributed version control play github的配置安装步骤:1.下载git bash(从http://www.git-scm.com ...
- AEAI CRM_v1.5.2升级说明,开源客户关系管理系统
1.升级说明 本次AEAI CRM升级内容主要是针对数通畅联推出AEAI ECP企业云联平台而升级的,其中对AEAI CRM的各模块进行扩展,同时增加了移动门户版功能及为AEAI ECP提供数据服务接 ...
- Hibernate 系列 05 - Session 类
引导目录: Hibernate 系列教程 目录 前言: Session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库的存取都与Session息息相关. 就如同在编写JDBC时需要关 ...
- mysql 常用自定义函数解析
-- /* -- * 用于获取一记录数据,根据传入的分隔字符delim,索引位置pos,返回相对应的value -- * SELECT Json_getKeyValue({"A": ...