Block小结
Blocks是C语言的扩充功能。用一句话来表示Blocks的扩充功能:带有自动变量(局部变量)的匿名函数。
block其实是一个代码块,但是它的神奇之处在于在内联(inline)执行的时候(这和C++很像)还可以传递参数。同时block本身也可以被作为参数在方法和函数间传递,这就给予了block无限的可能。
Block一般有如下几种使用情况:
1、作为一个本地变量(local variable)
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
2、作为@property
@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
3、作为方法的参数(method parameter)
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
4、作为方法参数的时候被调用
[someObject someMethodThatTakesABlock: ^returnType (parameters) {...}];
5、使用typedef来定义block,可以事半功倍
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
Block与C语言的函数指针是类似的
//C的函数
//格式:返回值 方法名 (参数...)
//1.返回值是void 没有参数的C函数
void cfun (void){
//调用时才执行函数里面的内容
printf("this is a c method\n");
}
//2.返回值是void 带两个参数的C函数
void cfun1(int a,int b){
printf("%d\n",a+b);
}
//3.有返回值 带两个参数的C函数
int cfun2(int c,int d){
int muli = c*d;
return muli;
} -(void)testC{
cfun();
cfun1(, );
int muli = cfun2(, );
NSLog(@"乘积是%d",muli); //1.声明一个返回值是void,不带参数的函数指针
//格式:返回值(*xxx)(参数...)
void (*fun1)(void);
fun1 = &cfun; //函数名本身就是一个地址,&可加可不加
fun1();
//2.声明一个返回值是void,带两个参数的函数指针
void (*fun2)(int a,int b);
fun2 = cfun1;
fun2(,);
//3.声明一个返回值是int,带两个参数的函数指针
int (*fun3)(int a,int b);
fun3 = cfun2;
NSLog(@"%d",fun3(,));
}
下面我们来看怎么定义Block
1.无参数无返回值的Block
/**
* void :就是无返回值
* emptyBlock:就是该 bloc k的名字
* ():这里相当于放参数。由于这里是无参数,所以就什么都不写
*/
void (^emptyBlock)() = ^(){
NSLog(@"无参数,无返回值的Block");
};
emptyBlock();
2.有参数无返回值的Block
/**
* 调用这个block进行两个参数相加
*
* @param int 参数A
* @param int 参数B
*
* @return 无返回值
*/
void (^sumBlock)(int ,int ) = ^(int a,int b){
NSLog(@"%d + %d = %d",a,b,a+b);
};
/**
* 调用这个sumBlock的Block,得到的结果是20
*/
sumBlock(,);
3.有参数有返回值的Block
/**
* 有参数有返回值
*
* @param NSString 字符串1
* @param NSString 字符串2
*
* @return 返回拼接好的字符串3
*/
NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){
return [NSString stringWithFormat:@"%@%@",str1,str2];
};
//调用logBlock,输出的是 我是Block
NSLog(@"%@", logBlock(@"我是",@"Block"));
那么block与函数指针有什么区别呢
首先:函数指针是对一个函数地址的引用,这个函数在编译的时候就已经确定了。而block是一个函数对象,是在程序运行过程中产生的。在一个作用域中生成的block对象分配在栈(stack)上,和其他所有分配在栈上的对象一样,离开这个作用域,就不存在了。Block允许开发者在两个对象之间将任意的语句当做数据进行传递,往往这要比引用定义在别处的函数直观。
其次:blocks是inline的,并且它对局部变量是只读的。
修改 block 之外的变量
默认情况下,在程序块中访问的外部变量是复制过去的,即写操作不对原变量生效。比如下面的语句:
- (void)viewDidLoad
{
//将Block定义在方法内部
int x = ;
void (^sumXAndYBlock)(int) = ^(int y){
x = x+y;
printf("new x value is %d",x);
};
sumXAndYBlock();
}
这段代码有什么问题呢,Xcode会提示x变量错误信息:Variable is not assigning (missing __block type),这时候给int x = 100;语句前面加上__block关键字即可,如下:
__block int x = ;//这样在Block的{}体内,就可以修改外部变量了。
Block循环引用
刚刚说过,block在iOS开发中被视作是对象,因此其生命周期会一直等到持有者的生命周期结束了才会结束。另一方面,由于block捕获变量的机制,使得持有block的对象也可能被block持有,从而形成循环引用,导致两者都不能被释放:
@interface ViewController (){
void (^_cycleReferenceBlock)(void);
} @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
_cycleReferenceBlock = ^{
NSLog(@"%@", self);
//引发循环引用
};
}
遇到这种代码编译器只会告诉你存在警告,很多时候我们都是忽略警告的,这最后会导致内存泄露,两者都无法释放。跟普通变量存在__block
关键字一样的,系统提供给我们__weak
的关键字用来修饰对象变量,声明这是一个弱引用的对象,从而解决了循环引用的问题:
__weak typeof(*&self) weakSelf = self;
_cycleReferenceBlock = ^{
NSLog(@"%@", weakSelf); //弱指针引用,不会造成循环引用
};
Block作为property属性实现页面之间传值
这里举例一个Block回调修改上一下界面的背景颜色。控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的背景颜色为红色。
VC2的实现
#import <UIKit/UIKit.h>
/**
* 定义了一个changeColor的Block。这个changeColor必须带一个参数,这个参数的类型必须为id类型的
* 无返回值
* @param id
*/
typedef void(^changeColor)(id);
@interface ViewController2 : UIViewController /**
* 用上面定义的changeColor声明一个Block,声明的这个Block必须遵守声明的要求。
*/
@property (nonatomic, copy) changeColor backgroundColor; @end
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//声明一个颜色
UIColor *color = [UIColor redColor];
//用刚刚声明的那个Block去回调修改上一界面的背景色
self.backgroundColor(color);
}
VC1的实现
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
ViewController2 *vc =[[ViewController2 alloc]init];
// 回调修改颜色
vc.backgroundColor = ^(UIColor *color){
self.view.backgroundColor = color;
};
[self.navigationController pushViewController:vc animated:YES];
}
Block小结的更多相关文章
- 块对象block小结(2)
MRC环境下 //// main.m// blcok//// Created by ios on 16/4/6.// Copyright © 2016年 ios. All rights res ...
- 块对象block小结
blcok的形式 ^(参数列){主体} block作为返回值
- inode与block知识总结
inode概述:硬盘要分区,然后格式化,创建文件系统在每个Linux存储设备的分区被格式化为ext3文件系统后一般有两个部分: 第一部分Inode:存储这些数据的属性信息(大小,属主,归属的用户 ...
- linux 基础 文件系统 用户权限
描述Linux系统的启动过程? 1.开机自检 BIOS 2.MBR引导 3.GRUB菜单 4.加载内核 5.运行init进程 6.从/etc/inittab读取运行级别 7.根据/etc/rc.sys ...
- linux运维、架构之路-linux文件属性
1.查看文件属性 ls -lhi 文件属性详细说明 1. 第一列: inode索引节点编号 2. 第二列:文件类型及权限 3. 第三列:硬链接数 4. 第四列:文件或目录所属的用户,即文件的所有者 5 ...
- Linux运维学习笔记-文件系统知识体系总结
文件系统知识总结 新买的硬盘要存放数据需要怎么做? 首先将硬盘装机做RAID,做完RAID后进行分区,分完区后格式化创建文件系统,最后存放数据. 硬盘的内外部结构: 物理形状: 接口类型: IDE(I ...
- 第一阶段·Linux运维基础 第3章·文件属性、正则表达式、文件权限
01-文件属性内容介绍 02- inodeyublock讲解 03-访问oldboyfile的寻宝过程 04-inode与block小结 05-磁盘空间不足案例详解 06-Linux文件类型及拓展名 ...
- 26.centos7基础学习与积累-012-文件和目录的属性
从头开始积累centos7系统运用 大牛博客:https://blog.51cto.com/yangrong/p5 1.文件的属性(文件的信息描述): [root@python01 ~]# ls -l ...
- JavaScript设计模式(一):单例模式
单例模式的定义与特点 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式.例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗 ...
随机推荐
- 学习WindowsPhone 2013/12/22
菜鸟一枚,只能边看别人的博客变学习来提升自己,参考博客内容:http://blog.csdn.net/column/details/wp-comming.html?page=3 ,稍微看了一下,写的还 ...
- 在uboot上创建菜单
一.原理 菜单其实就是一个uboot中的命令,和其他的命令没有什么差别. uboot启动时,如果进入uboot命令模式,先运行这个命令,就会打印出一个菜单界面. 在uboot的命令模式,通过键入“m ...
- Nine Great Books about Information Visualization
Nine Great Books about Information Visualization Maybe it’s anachronistic to celebrate static, print ...
- Tomcat8 配置Oracle11g数据源
1:context.xml <Resource name="jdbcoracle" auth="Container" type="javax.s ...
- Spring中用@Component、@Repository、@Service和 @Controller等标注的默认Bean名称会是小写开头的非限定类名
今天用调度平台去调用bean中的方法时,提示找不到bean.经查,发现是由于如果在标注上没有提供name属性值,则默认的bean名称是小写开头的,而不是大写开头的. 下面是其他文档参阅: 使用过滤器自 ...
- Delphi中的THashTable
在Delphi中,Inifiles单元中有一个TStringHash的类,不过它的Value仅支持Integer(其实也不是问题,有其它类型可以将变量变为Pointer),有点不舒服,今天没事做就把它 ...
- Spring的OpenEntityManagerInViewFilter
在Java Web项目中使用Hibernate经常会遇到LazyInitializationException .这是因为controller和model层(java代码)将通过JPA的一些启用了延迟 ...
- 矩阵(快速幂):COGS 963. [NOI2012] 随机数生成器
963. [NOI2012] 随机数生成器 ★★ 输入文件:randoma.in 输出文件:randoma.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 栋 ...
- Vim笔记
复制多行: v 可视化,选择多行,然后yy复制.
- [基础] C++与JAVA的内存管理
在内存管理上(总之一句话——以后C++工程,一定要用智能指针!) 1.同是new一个对象,C++一定得手动delete掉,而且得时刻记住能delete的最早时间(避免使用空指针).JAVA可以存活于作 ...