block有哪些类型

Python021

block有哪些类型,第1张

block的类型

block如何分类?其实blcok的分类主要是根据block的内存管理来说的,系统把Block分为3类:NSGlobalBlock,NSStackBlock, NSMallocBlock

NSGlobalBlock :位于内存全局区

NSMallocBlock :位于内存堆区

NSStackBlock :位于内存栈区

内存五大区

栈区,堆区,静态区(全局区),常量区,代码区

动态数据区一般就是”堆栈”,栈是线性结构,堆是链式结构. 本地变量在堆栈中.通过堆栈的基地址和偏移量来访问本地变量

动态内存分配有系统根据程序需要即时分配,且分配的大小就是程序要求的大小.

全局变量(一般用static修饰的变量)和静态变量分配在静态区(需要预先分配存储空间)

静态内存分配:分配固定大小的内存分配方法,大多情况下会浪费大量的内存空间,少数情况下,当定义的数组不够大时,会引起越界.

block的结构体如下

Block是带有自动变量的匿名函数

有三种类型的Block:

_NSConcreteGlobalBlock

_NSConcreteStackBlock

_NSConcreteMallocBlock     

Block截获外面的自动变量:

全局变量不会被截获;

没有被__block修饰的int,block体中对这个变量的引用是值拷贝,在block中是不能被修改的;

通过__block修饰的int,block体中对这个变量的引用是指针拷贝,它会生成一个结构体,复制这个变量的指针引用,从而达到可以修改变量的作用;

Block发生copy时机:

block作为方法或函数的返回值时,编译器会自动完成copy操作。

当block赋值给通过strong或copy修饰的id或block类型的成员变量时。

当 block 作为参数被传入方法名带有 usingBlock 的 Cocoa Framework 方法或 GCD 的 API 时。

带有自动变量(局部变量)的 匿名函数 。这个定义满足以下三点:

1.block是一个函数

2.block是一个没有名字的函数

3.block有参数列表,但是这个参数列表是局部变量

block经常使用省略语法,那么意味着省略了一些不必要的东西,我们一步步解析。

1.block完整语法:

                          ^ 返回值类型 参数列表 表达式

                          ^int (int count){ return count + 1}

2.省略返回值类型后:

                          ^ 参数列表 表达式

                          ^ (int count){ return count + 1}

3.省略参数与返回值后:

                          ^ 表达式

                          ^{ printf("Blocks")}

可以看到,对比正常函数语法:

                       - 返回值类型 函数名 参数列表 表达式 

                       - int name(int count) { return count + 1}

完整语法block实际上与普通函数的区别在于, 没有函数名,并使用 ^ 来表明是block函数。

block也可以作为变量使用,正常定义变量时,需要给出变量类型以及变量名,使用block也是如此。

声明block类型的变量格式如下:

                                                返回值 ^变量名 参数

                                                int (^blk) (int )

我们看到,block变量和正常变量区别在于,多了返回值,以及参数。那我们又该如何赋值呢?

block变量赋值方式:

                                             变量 = 具体block语法

                                            int (^blk) (int ) =  ^int (int count){ return count + 1}

这很好理解,block变量也是block类型,赋值时一定也是等于具体的block。

这里,我们来讲一些block作为变量使用的方式,

1.通过Typedef 在函数参数和返回值中使用Block变量:

首先要定义      typedef int(^blk_t)(int)

block作为函数参数     void func(blk_t blk){   }

block作为函数返回值   blk_t func(){    }

2.

typedef int(^blk_t)(int)

blk_t blk = ^(int count){return count + 1}

int result = blk(10)

1.“带有自动变量值”在Blocks中表现为“截获自动变量值”,在Block被赋值时获取当时的变量值并在以后使用。

int value = 2

void (^block)(void) = ^{

     NSLog(@"%i",value) 

}

value = 10

block()//输出 2

2.未添加__block的情况下:截获OC对象, 调用变更对象的方法不会有问题 ,因为block内会截获该对象的结构体实例指针.但是 不能对该对象进行赋值 操作

id array = [[NSMutableArray alloc] init]

void (^blk) (void) = ^{

        id obj = [[NSObject alloc] init]

         [array addObject:obj]//这是可行的

         array = [[NSMutableArray alloc] init]//这是不可行的

}

若想在Block的表达式中将值赋给外部声明的自动变量,需要在该自动变量上附加__block

__block int value = 2

void (^block)(void) = ^{ value = 10}

block()

NSLog(@"%i",value)//输出10