您的位置:首页 > 移动开发 > IOS开发

iOS之block基础及传值

2015-09-13 23:30 465 查看
最近碰到不少关于block的相关问题,在此做一些总结。

1.基本形式

返回值类型(^block)(形参列表)= ^(形参列表列表){代码段;};

eg: int(^block)(int,int) = ^(int i, int j){return i + j;};

定义没有参数的三种写法:

当没有形参时,左边形参列表括号必须写,右边可写可不写,左边形参类型可写可不写;

void(^block)() = ^(){};

void(^ block)() = ^{};

void(^ block)(void) = ^{};

typedef定义Block类型

typedef int (^Block)(int, int);

//加上typedef之后,Block不再是一个变量,而是一个数据类型

Block b1, b2;

//使用typedef声明的变量类型定义另个变量

2.块对象作形参和块对象作函数返回值

void fun(int (^b)(int x, int y))
{
NSLog(@"b(3, 4) = %d", b(3, 4)); //在fun函数内部调用代码块,并传参。
}

int main()
{
//1,直接在实参位置定义block代码块,这时候 如下的 int 表示代码块的返回值类型,可以写可以不写,不写的时候,程序会根据形参的返回值类型做类型转换,一般情况这里还是写返回值类型为好,避免不必要的错误。
fun(^int(int x, int y) {
return x + y;
});
//2,先定义一个block代码块,再将代码块类型的变量作为实参传给fun函数。
int (^block)(int, int) = ^(int a, int b){
return a * b;
};
fun(block);


3.块对象中的变量行为

1)在block代码块内部可以访问定义的全局变量,局部变量,静态局部变量,但是访问局部静态变量时候是只读的并且局部变量和在代码块中访问到的不是同一个地址的变量,他们在数值上相等,互相似乎没什么联系。 因为代码块中使用到局部变量的时候,会将局部变量进行const类型的copy,所以在代码块中访问到的局部变量都是只读的;静态变量和全局变量都存放在静态区,在程序运行过程中都存在,他们可以在不同的代码块中共享,不同代码块中访问到的同一个全局变量,局部变量是同一块内存的数据;对于普通局部变量在代码块中只读,全局变量和静态局部变量在代码块中可以读写。

2)在块句法的主体中,除块句法内部的局部变量和形参之外,还包含块句法当前位置处可以访问的变量;这些变量中包含外部变量也包含块中可以访问的局部变量。

3)代码块中访问局部变量时候,局部变量会从栈内存被const类型的copy一份到堆内存中。

4)块对象和函数指针的定义使用功能都差不多,块对象的精髓之处就在于,在块对象中可以访问到上下文的变量,而函数指针不能

4,块对象的实例和生命周期

1)块句法也可以写在函数的外部,当写在函数外面时候,只是在静态数据区分配一块内存给块对象,这块区域在程序执行期间会一直存在。

2)块句法写在函数内部的时候,块对象和变量的生命周期和普通局部变量一样,块对象的内存区域会在执行包含块对象的函数时保存在栈上;该块对象的生命周期就是函数运行期间。

3)在现实的实现中,当函数内的块语法不包含自动变量的时候,就没必要进行复制值,所以块对象的内存区域也会被保存在静态数据区。

4)block代码块被保存在堆或者静态区中,不会被保存在栈中,如下图可以说明这一点。



5,块对象的复制

函数内的块对象和局部变量的生命周期相同,都只是在函数的执行期间。但是在函数的方法调用参数中直接代入块对象也是块对象的一种非常常见的用法,这时候使用与函数调用关系或栈状态无关的块对象是非常必要的。

有一个函数可以复制块对象到新的堆内存,通过使用该函数,即使是在函数内部定义的块对象也能独立于栈被持续的使用,此外还有一个函数可以释放不需要的块对象。

Block_copy( block )

参数为栈上的块对象的时候,返回堆上的块对象。参数为堆上的块对象或者静态区的块对象,不进行复制,直接返回原对象,但是会增加参数块对象的引用计数。

Block_release( block )

减少参数块对象的引用计数。当引用计数减到0时候,块对象被释放。

Eg:

a = Block_copy(block);

Block_rlease(a);

6.指定特殊变量 __block

ARC环境下



非ARC环境下



7.Block传值示例及注意事项

detailView页面是第二层页面,此处是从下级往上级传值

DetailViewController.h
typedef void (^BLOCK)(NSString * string) ;//block的声明
@property (copy ,nonatomic)BLOCK  block;

DetailViewController.m
-(void)viewDidDisappear
{
self.block(self.textField.text);//传值
}

SecondViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController * detailVC = (DetailViewController*)segue.destinationViewController;

//block赋值
__block SecondViewController * secondVC = self;//防止循环使用
detailVC.block = ^void(NSString * string){
secondVC.navigationItem.title = string;
};//注意分号
}


1.block没有层级限制,可以从下往上,也可从上级往下级传

2.block不容易找到实现方法的地方

3.声明block属性时用copy修饰
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: