您的位置:首页 > 其它

block总结

2016-03-10 15:10 417 查看
1.是什么?

一种特殊的数据类型

2.有什么用?

用于保存代码块

3.怎么用?

>1.声明block的快捷键:

inlineBlock

>2.block的声明:

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
<#statements#>
};


>3.声明/初始化/调用

//声明
void(^myBlock1)();//无参无反
int(^myBlock2)();//无参有反
void(^myBlock3)(int);//有参无反
int(^myBlock4)(int,int);//有参有反

//初始化
myBlock1 = ^()
{
NSLog(@"无参无反");
};

myBlock2 = ^()
{
return 3;
};

myBlock3 = ^(int a)
{
NSLog(@"%d",a);
};

myBlock4 = ^(int a,int b)
{
return a + b;
};

//调用
myBlock1();
int num = myBlock2();
myBlock3(3);
int sum = myBlock4(3,4);


>4.给block起别名

返回值类型 (^别名)(参数);

例:

typedef void(^myBlock)();//给第一个无参无反的block起别名myBlock,myBlock就称为一种数据类型


使用:

myBlock block1 = ^(){
NSLog(@"声明和定义不同,声明仅仅是声明一个变量(开辟一块内存空间),并不初始化,定义包含了初始化,像这样即是声明的同时初始化了");
};


像这样仅仅是声明了一个myBlock类型的变量:

myBlock block2;
myBlock block3;
myBlock block4;


因为block是一种数据类型,因此数据类型所具有的所用特性block都具有,可以声明变量;作为参数;作为返回值;

>5.block作为函数参数

>例一:

typedef int(^myBlock2)();
typedef int(^myBlock3)(int);


int sum(myBlock2 m,myBlock3 n,int a)//a为myBlock3需要的参数
{
//    int num1 = m();
//    int num2 = n(a);
//    return num1 + num2;
return m() + n(a);
}


//block作为函数参数
myBlock2 m = ^(){
return 10;
};

myBlock3 n = ^(int a)
{
return a;
};

int num = sum(m, n, 10);

NSLog(@"%d",num);//输出20;


此种方式并不常用.常用的情景是:比如有三个函数,开头和结尾部分执行的代码一样,中间有部分代码不同,那么就可以将中间部分抽取为block,将三个函数变为一个,调用三次该函数,传入不同的block即可.

>例二:

void test1() {

NSLog(@"AAAAAAAAAAAAAAAAAAAA");

NSLog(@"星期天,今天去哪儿浪呢?");

NSLog(@"BBBBBBBBBBBBBBBBBBBB");

}

void test2() {

NSLog(@"AAAAAAAAAAAAAAAAAAAA");

NSLog(@"星期一,昨天玩的好累不想上班.");

NSLog(@"BBBBBBBBBBBBBBBBBBBB");

}

void test3() {

NSLog(@"AAAAAAAAAAAAAAAAAAAA");

NSLog(@"星期二,昨天的任务还没完成");

NSLog(@"BBBBBBBBBBBBBBBBBBBB");

}


通过block优化,分析中间部分代码,不需要参数,返回值,定义无参无反的block:

typedef void(^myBlock)()


将四个函数抽取为一个

void test(myBlock myLife) {

NSLog(@"AAAAAAAAAAAAAAAAAAAA");

  if(myLife){//判断block是否为nil,否则可能报错,会报什么错呢?,为什么是nil呢,nil不是用于OC对象为空的情况么?block是基本数据类型?还是OC类型?

myLife();
  }

NSLog(@"BBBBBBBBBBBBBBBBBBBB");

}


main函数中就可以这样写:

test(^(){
NSLog(@"星期天,今天去哪儿浪呢?");
});
test(^(){
NSLog(@"星期一,昨天玩的好累不想上班.");
});
test(^(){
NSLog(@"星期二,昨天的任务还没完成");
});


>6.作为函数返回值

typedef void(^myBlock)();

myBlock test4()
{
return ^(){

};
}


>7.利用block在不同对象间进行传值

假设A需要传值给B,那么需要在A中定义一个block属性,在需要的时候传递值,先判断是否为nil,不为nil则调用block.

需要在B中声明一个属性(有东西接收就可以,不一定就要定义属性),用以接收传递过来的值,B必须拿到A,比如A成为B的属性,那么就可以获取A的block属性,并定义,判断的时候,block就已经定义了,就可以实现传值了.

例子:

控制器的View上有一个绿色的View,当点击屏幕的时候,传递一个NSInteger数据给控制器.

分析:

绿色的View为数据的传递者,控制器为接收者,因此,需要给绿色的View声明一个block类型的属性,因此自定义一个GreenView的类用于描述绿色的View,并在其中声明block属性

typedef void(^GreenViewBlock)(NSInteger index);
@property (nonatomic,copy) GreenViewBlock myBlock;


当点击屏幕的时候传递数据,因而重写touchesBegin方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (_myBlock) {//如果实现了,就调用
_myBlock(11);
}
}


控制器为接收者,因而给控制器声明一个属性用于接收数据,又因为,需要在控制器中初始化block,这样点击屏幕是block不为nil,实现传值,因而需要获得绿色的View的属性block,因而,将绿色的View拖成控制器的属性

@property (nonatomic,assign) NSInteger index;

@property (weak, nonatomic) IBOutlet GreenView *greenView;


//初始化block
_greenView.myBlock = ^(NSInteger index){
self.index = index;
};


//上面的赋值操作即是调用index的setter方法,因而此时即可获得传递过来的数据
- (void)setIndex:(NSInteger)index
{
_index = index;
NSLog(@"%ld",index);
}


>8.注意:

block内部默认不能修改外部的局部变量



用__block修饰局部变量,在block中就可以访问了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: