Block 及注意事项
block
概念
- block 是 C 语言的
- 是一种数据类型,可以当作参数传递
- 是一组预先准备好的代码,在需要的时候执行
block 的注意事项
(1)block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝。
(2)非内联(inline) block 不能直接访问 self,只能通过将 self 当作参数传递到 block 中才能使用,并且此时的 self 只能通过 setter 或 getter 方法访问其属性,不能使用句点式方法。但内联 block 不受此限制。
(3)使用 weak–strong dance 技术来避免循环引用
(4)block 内存管理分析
block 其实也是一个 NSObject 对象,并且在大多数情况下,block 是分配在栈上面的,只有当 block 被定义为全局变量或 block 块中没有引用任何 automatic 变量时,block 才分配在全局数据段上。 __block 变量也是分配在栈上面的。在 ARC 下,编译器会自动检测为我们处理了 block 的大部分内存管理,但当将 block 当作方法参数时候,编译器不会自动检测,需要我们手动拷贝该 block 对象。
在 ARC 下,对 block 变量进行 copy 始终是安全的,无论它是在栈上,还是全局数据段,还是已经拷贝到堆上。对栈上的 block 进行 copy 是将它拷贝到堆上;对全局数据段中的 block 进行 copy 不会有任何作用;对堆上的 block 进行 copy 只是增加它的引用记数。
如果栈上的 block 中引用了__block 类型的变量,在将该 block 拷贝到堆上时也会将 __block 变量拷贝到堆上如果该 __block 变量在堆上还没有对应的拷贝的话,否则就增加堆上对应的拷贝的引用记数。
block 基本演练
1 最简单的 block
- (void)blockDemo1 {
// 定义block
// 类型 变量名 = 值
void (^block)() = ^ {
NSLog(@"Hello block");
};
// 执行
block();
}
tip :使用 inlineBlock 可以快速定义 block.
- 当作参数传递
- (void)blockDemo2 {
void (^block)() = ^ {
NSLog(@"Hello block");
};
[self demoBlock:block];
}
/// 演示 block 当作参数传递
- (void)demoBlock:(void (^)())completion {
NSLog(@"干点什么");
completion();
}
- 使用局部变量
- (void)blockDemo3 {
// 栈区变量
int i = 10;
NSLog(@"%p", &i);
void (^block)() = ^ {
// 定义 block 的时候会对栈区变量进行一次 copy
NSLog(@"Hello block %d %p", i, &i);
};
[self demoBlock:block];
}
如果 block 中使用了外部变量,会对外部变量做一次 copy
- 在 block 中修改外部变量
- (void)blockDemo4 {
// 栈区变量
__block int i = 10;
NSLog(@"%p", &i);
void (^block)() = ^ {
// 定义 block 的时候会对栈区变量进行一次 copy
NSLog(@"Hello block %d %p", i, &i);
i = 20;
};
NSLog(@"block 定义完成 %p %d", &i, i);
[self demoBlock:block];
NSLog(@"===>%d", i);
}
如果要在 block 内部修改栈区变量,需要使用 __block 修饰符,并且定义 block 之后,栈区变量的地址会变化为堆区地址
block 的内存位置
- 全局区:如果block中没有使用任何全局变量
- 栈区:如果 block 中使用了外部变量
MRC 模式可以看到
ARC 模式,系统会自动将 Block 复制到堆中
- 堆区:将 block 设置给 copy 属性
@property (nonatomic, copy) void (^myBlock)();
- (void)blockDemo5 {
int i = 10;
void (^block)() = ^ {
NSLog(@"i --- %d", i);
};
NSLog(@"%@", block);
self.myBlock = block;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"%@", self.myBlock);
}
注意:虽然目前 ARC 编译器在设置属性时,已经替程序员复制了 block,但是定义 block时,仍然建议使用 copy 属性
Block 及注意事项的更多相关文章
- ObjectiveC中的block用法解析
Block Apple 在C, Objective-C,C++加上Block这个延申用法.目前只有Mac 10.6 和iOS 4有支持.Block是由一堆可执行的程序组成,也可以称做没有名字的Func ...
- OC语言Block 续
OC语言 Block 转载:http://blog.csdn.net/weidfyr/article/details/48138167 1.Block对象中的变量行为 结论: 在block代码块内部可 ...
- iOS7新JavaScriptCore框架入门介绍
前阵子,Apple正式发布了新的iOS 7系统,最大最直观的改变在于界面变得小清新范了,我也提到<iOS,你真的越来越像Android了>.不过对于移动开发者来说,除了要适应Xcode 5 ...
- ios7 JavaScriptCore.framework
曾经想要oc调用js代码通常是通过uiwebview的stringByEvaluatingJavaScriptFromString方法,或是直接使用JavaScriptCore引擎,比如https:/ ...
- django (装饰器,母版继承,自定义,request对象,response对象)
1. 装饰器 1. def wrapper(fn): def inner(*args,**kwargs): 执行被装饰函数之前的操作 ret = fn(*args,** ...
- django 模版 语法与使用
目录 django 模版语法与使用 django模板语言介绍 (摘自官方文档) 链接 什么是模板? 模板语句的 注释 变量 {{ 变量 }} 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值 ...
- oc62--block1
// // main.m // Block的应用场景 // typedef void (^workBlock)(); #import <Foundation/Foundation.h> / ...
- JavaScriptCore
在移动的混合开发中经常用到OC与JS的交互,就涉及iOS中的JavaScriptCore类,下面终结如下 JavaScriptCore中的类 在项目中引入JavaScriptCore后,链到头文件中, ...
- Django 模版语法与使用
目录 Django 模版语法与使用 django模板语言介绍 (摘自官方文档) 链接 什么是模板? 模板语句的 注释 变量 {{ 变量 }} 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值 ...
随机推荐
- js-JavaScript高级程序设计学习笔记3
第五章 引用类型 1.使用new操作符和Date构造函数创建日期对象. 2.创建特定日期有两个方法--Date.parse()和Date.UTC().后者小时数为0时显示时间是8点,应该是因为本地是东 ...
- ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet
严重: Context initialization failedorg.springframework.beans.factory.BeanDefinitionStoreException: Fai ...
- javascript向上向下取整
alert(Math.ceil(25.9)); alert(Math.ceil(25.5)); alert(Math.ceil(25.1)); alert(Math.round(25.9)); ale ...
- Jenkins/CCNET发送邮件策略和注意事项,以及邮箱类型的选择
QQ邮箱永远也不要用,原因:安全机制太强导致在CCNET/Jenkins中极难配置,且反垃圾太强,有些项目会涉及到敏感词一样屏蔽,如果发邮件找客服求助时,基本是无果. 如果在免费领域,推荐使用免费企业 ...
- 关于git的学习
Git是目前世界上最先进的分布式版本控制系统(没有之一)! 由于现在用的还不多,还没有这种体会,但是前人的经验是值得借鉴的,所以我认真的学习了一些关于git的简单操作,现在在这分享一些心得,或者说是为 ...
- Android成长日记-ContextMenu实现上下文菜单
一. ContextMenu的组成 标题以及标题图标 菜单内容 菜单内容的点击事件 二. ContextMenu与OptionMenu的区别 OptionMenu对应的是activity,一个acti ...
- UVa 101 The Blocks Problem Vector基本操作
UVa 101 The Blocks Problem 一道纯模拟题 The Problem The problem is to parse a series of commands that inst ...
- dedecms /member/mtypes.php SQL Injection Vul
catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 Relevant Link http:/ ...
- CSS基础知识真难啊
CSS层叠样式表Cascading Style Sheets CSS派生选择器(上下文选择器): 后代选择器:h1 strong {color:red;}第一个参数和第二个参数之间的代数是可以无限的 ...
- Markdown编辑器简单总结
字体大小: #1 ##2 添加链接: 文字链接 [blog](http://yalantis.com/blog/how_we_created_tab_bar_animation_for_ios/?ut ...