iOS开发之Block
1、定义
(1) Block是OC中的一种数据类型,在iOS开发中被广泛使用
(2) ^是Block的特有标记
(3) Block的实现代码包含在{}之间
(4) 大多情况下,以内联inline函数的方式被定义和使用
(5) Block与C语言的函数指针有些相似,但使用起来更加灵活
例如:
void(^demoBlock)() = ^ {
NSLog(@"demo Block");
};
int(^sumBlock)(int, int) = ^(int x, int y) {
return x + y;
};
格式说明:
(返回类型)(^块名称)(参数类型) = ^(参数列表) {代码实现};
如果没有参数,等号后面参数列表的()可以省略
2、常见相关面试题
Block可以使用在定义之前声明的局部变量:
int i = 10;
void(^myBlock)() = ^{
NSLog(@"%d", i);
};
i = 100;//实际上并没效果
myBlock();
输出结果为:10
注意:
(1) 在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)
(2) 后续再对该变量的数值进行修改,不会影响Block中的数值
(3) 如果需要在block中保持局部变量的数值变化,需要使用__block关键字
(4) 使用__block关键字后,同样可以在Block中修改该变量的数值
3、当做参数传递
Block可以被当做参数直接传递:
NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"第 %d 项内容是 %@", (int)idx, obj);
if ([@"王五" isEqualToString:obj]) {
*stop = YES;
}
}];
说明:遍历并NSLog() array中的内容,当obj 为"王五"时停止遍历
4、使用局部变量
在被当做参数传递时,Block同样可以使用在定义之前声明的局部变量:
int stopIndex = 1;
NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"第 %d 项内容是 %@", (int)idx, obj);
if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
注意,默认情况下,Block外部的变量,在Block中是只读的!
BOOL flag = NO;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
flag = YES; // 编译错误!!!
}
}];
5、__block关键字
如果要修改Block之外的局部变量,需要使用__block关键字
__block BOOL flag = NO;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
flag = YES; // 现在可以修改了!!!
}
}];
提示:无需使用__block关键字,在块代码中可以修改成员变量的数值(比较少用)
6、传递对象
对象传递进Block的方式
NSString *stopName = @"王五";
NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"第%d项内容是%@", (int)idx, obj);
if ([stopName isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
为保证Block中的代码正常运行,在将stopName的指针传递给Block时,Block会自动对stopName的指针做强引用
7、Block在栈区工作示意图
8、typedef
可以使用typedef定义一个Block的类型,便于在后续直接使用
typedef double(^MyBlock)(double, double);
MyBlock area = ^(double x, double y) {
return x * y;
};
MyBlock sum = ^(double a, double b) {
return a + b;
};
NSLog(@"%.2f", area(10.0, 20.0));
NSLog(@"%.2f", sum(10.0, 20.0));
说明:
(1) typedef是关键字用于定义类型,MyBlock是定义的Block类型
(2) area、sum分别是MyBlock类型的两个Block变量。
尽管,typedef可以简化Block的定义,但在实际开发中并不会频繁使用typedef关键字。
这是因为Block具有非常强的灵活性,尤其在以参数传递时,使用Block的目的就是为了立即使用。
官方的数组遍历方法声明如下:
而如果使用typedef,则需要:
(1) typedef void(^EnumerateBlock)(id obj, NSUInteger idx, BOOL *stop);
(2) - (void)enumerateObjectsUsingBlock:(EnumerateBlock)block;
而最终的结果却是,除了定义类型之外,EnumerateBlock并没有其他用处。
9、添加到数组
既然Block是一种数据类型,那么可以将Block当做比较特殊的对象
#pragma mark 定义并添加到数组
@property (nonatomic, strong) NSMutableArray *myBlocks;
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
int(^area)(int, int) = ^(int x, int y) {
return [self area:x y:y];
};
[self.myBlocks addObject:area];
#pragma mark 调用保存在数组中的Block
int(^func)(int, int) = self.myBlocks[index];
return func(x, y);
10、循环引用
@property (nonatomic, strong) NSMutableArray *myBlocks;
#pragma mark 将代码改为调用self的方法
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
#pragma mark 对象被释放时自动调用
- (void)dealloc
{
NSLog(@"DemoObj被释放");
}
11、解除循环引用
局部变量默认都是强引用的,离开其所在的作用域之后就会被释放。
使用__weak关键字,可以将局部变量声明为弱引用
__weak DemoObj *weakSelf = self;
在Block中引用weakSelf,则Block不会再对self做强引用
int(^sum)(int, int) = ^(int x, int y) {
return [weakSelf sum:x y:y];
};
iOS开发之Block的更多相关文章
- iOS 开发之Block
iOS 开发之Block 一:什么是Block.Block的作用 UI开发和网络常见功能的实现回调,按钮事件的处理方法是回调方法. 1. 按钮事件 target action 机制. 它是将一 ...
- 李洪强iOS开发之Block和协议
李洪强iOS开发之Block和协议 OC语言BLOCK和协议 一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任 ...
- IOS开发之block应用
非常长时间都是在学习各位大神的力作,并汲取了不少养料,在此一并谢过各位大神了. 当然了.好东西是要跟大家一起分享的,近期发现了几个很不错的个人网站,都是介绍IOS开发的.当中有唐巧.破船之长.池建强. ...
- ios开发之block的使用,及注意事项
转自:http://my.oschina.net/u/1432769/blog/390401 Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是一回事.需要注意的是由于 ...
- iOS开发之block解析
1. block的本质是一个Objective-C的对象,为什么这么说? 在Objective-C中,runtime会在执行时依据对象的isa指针的指向,来度额定这个对象的类型,也能够觉得一个对象,它 ...
- iOS 开发之 GCD 不同场景使用
header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...
- iOS 开发之 GCD 基础
header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...
- iOS开发之MVVM在项目中的应用
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 李洪强iOS开发之RunLoop的原理和核心机制
李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...
随机推荐
- 如何在Oracle中复制表结构和表数据 【转载】
1. 复制表结构及其数据: create table table_name_new as select * from table_name_old 2. 只复制表结构: create table ta ...
- UI进阶 即时通讯之XMPP登录、注册
1.XMPP环境搭建 http://www.cnblogs.com/fearlessyyp/p/5506644.html 第一次打开可能会有点儿慢,图片很多,步骤很详细,祝搭建成功. 2.工程中添加X ...
- 读书笔记 effective c++ Item 1 将c++视为一个语言联邦
Item 1 将c++视为一个语言联邦 如今的c++已经是一个多重泛型变成语言.支持过程化,面向对象,函数式,泛型和元编程的组合.这种强大使得c++无可匹敌,却也带来了一些问题.所有“合适的”规则看上 ...
- jenkins全局安全设置
如何进入安全设置界面 在Jenkins的主界面,点击 configure Global Security 选项,进入Jenkins的系统安全设置界面.安全界面如下图.在这里我们分别介 ...
- ajaxFileUpload.js 无刷新上传图片,支持多个参数同时上传,支持 ie6-ie10
/* 131108-xxj-ajaxFileUpload.js 无刷新上传图片 jquery 插件,支持 ie6-ie10 依赖:jquery-1.6.1.min.js 主方法:ajaxFileUpl ...
- 2017-2-19 C#基础 数据类型
数据类型分为基本数据类型和引用类型.基本数据类型分为两大类,值类型,字符型(char)和布尔型(bool).其中值类型分为整型和浮点型.整型分为byte,short,int,long.常用的是int( ...
- Manual | BSD手册| Linux手册 | 数据库手册 | 编程开发手册 | WEB开发手册 | 软件应用手册 | 网络技术手册 | GNU手册
豆豆手册 □ BSD手册 □ Linux手册 □ 数据库手册 □ 编程开发手册 □ WEB开发手册 □ 软件应用手册 □ 网络技术手册 □ GNU手册 在线手册 首 页 BSD手册 ·FreeBS ...
- 了解 : angular $filter stateful
{{ abc | myFilter }} angular.module('myStatefulFilterApp', []) .filter('decorate', ['decoration', fu ...
- 日常:css样式、选择器、个别知识点、数组array
优先加入css引入文件定义,个别的在下面用style改变.(从左往右,从上往下)CSS样式表1.内联样式表(优先级最高)(改个别的)<div style="width:100px; h ...
- Javascript学习十
认识DOM 文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法.DOM 将HTML文档呈现为带有元素.属性和文本的树结构(节点树). 先来看看下面代码 ...