Block的详细使用(五)
2017-12-11 本文已影响11人
凉白开0072
Block 的初步理解
- 例如定义一个block:
void(^myblock)(int);=>与int a;
比较 - block的类型:
void(^)(int);
=>等价于int
- block的变量名:
myblock
=>等价于a
- 注意:
- 定义block时若有输入参数(本例为int),参数名可有(int x)可无(int)但必须有参数的类型,但实现是必须有参数的类型和变量名.
- 实现block时,也可以将block返回类型写在实现中(通常不写),写在仅仅挨着
^
后面,不需要(),这样有利于让实现者知道该block返回什么值,(其实这样写更加规范,苹果官方有使用:当带有返回值的block作为一个方法的参数时,当调用这个方法时,系统的提示代码在block实现中会加上返回类型,具体看典例)
//实现中写返回参数类型
NSString *(^myblockx)(int) = ^NSString *(int a){
return @"";
};
//实现中不写返回参数类型
NSString *(^myblockx2)(int) = ^(int a){
return @"";
};
定义一个block
-
无返回值有参数
//定义一个block变量,然后给这个变量赋值:myblock //此时void(^)(int)为类型名,myblock1为变量名 //int a ; a = 3; void(^myblock1)(int); myblock1 = ^(int a){ }; //定义一个block变量并赋值//int a = 3; void(^myblock2)(int) = ^(int a){ };
-
无返回值无参数
//1.先定义,在赋值 void(^myblock0)(); myblock0 = ^{ }; //2.定义时赋值(略)
-
有返回值无参数
//1.先定义,在赋值(略) //2.定义时赋值 int(^myblock4)()=^{ return 3; };
-
有返回值有参数且参数(注意参数中可以有变量名也可以没有变量名,变量名与实现时参数的变量名无关联)
//1.先定义,在赋值 int(^myblock7)(int c ,int d); myblock7 = ^(int a, int b){ return a + b; }; //2.定义时赋值 int(^myblock6)(int ,int) = ^(int a, int b){ return a + b; };
-
参数为block
//重要:block的传入参数为block类,理解!!!! //1.定义时赋值(参数block无变量名) //同理当传入参数为block时,可以有变量名,也可以无变量名 //传入的block类型为void(^)():无返回值无参数型 int(^blockx)(void(^)())= ^(void(^x)()){ return 2; }; //2.先定义,在赋值(参数block有变量名:mmm,参数block中的参数名q也是可有可无) //传入的block类型为int(^)(int):有返回值有参数型 int(^blocky)(int(^mmm)(int q)); blocky = ^(int(^x)(int a)){ return 2; };
使用typedef定义block类
- 面向对象思想:将block定义成一个自定义类,然后使用这个类创建变量赋值block,使用typedef
//定义一个sumblock类(参数中的变量名可有可无)
typedef int(^sumblock)(int c ,int d);
sumblock block = ^(int a,int b){
return a + b;
};
//实质:
// sumblock block;等价于 int(^block)(int,int);
//用block替换掉sumblock;
//举例:定义一个blockz,传入参数为sumblock类,然后赋值
//sumblock只是类型,变量名可有可无,也可以传入sumblock vvv
int(^blockz)(sumblock);
blockz = ^(sumblock block2){
return 2;
};
Block的常见使用
- block成为属性
-
举例:
@property (nonatomic, strong) void(^operation)(); @property (nonatomic, strong) NSString *operation;
-
作用: 把block保存到对象中,恰当时机的时候才去调用
-
注意:这里容易引发循环引用,引起原因前面讲过,如何解决(weakself),不再赘述.
-
- block成为方法参数:传入一个block参数
-
举例:
- (void)eat:(void(^)(int))block; - (void)eat:(nsstring *)block;
-
作用: 把block当做方法的参数使用,外界不调用,都是方法内部去调用,Block实现交给外界决定.(注意理解)
-
- 成为返回参数:该方法返回一个block
-
举例:
- (void(^)(int))run; -(nsstring *)run;
-
作用:把block当做方法的返回值,目的就是为了代替方法,block交给内部实现,外界不需要知道Block怎么实现,只管调用
-
举例使用:
//Person.h
#import <Foundation/Foundation.h>
// name:类型的别名
typedef void(^BlockName)();
@interface Person : NSObject
//block作为属性
// block:既可以使用copy,也可以使用strong,但是建议用copy
// block类型:void(^)()
@property (nonatomic, strong) void(^operation)();
//block 作为参数
// 参数类型:block类型
- (void)eat:(void(^)())block;
- (void)eat2:(BlockName)block;
//传入参数block带返回值类型
- (void)eat3:(NSString *(^)(int))block;
//block作为返回值
- (void)run:(int)metre;
- (void(^)(int))run;
@end
#import "Person.h"
@implementation Person
- (void)eat:(void (^)())block
{
block();
}
-(void)eat3:(NSString *(^)(int))block{
block(3);
}
- (void)run:(int)metre
{
NSLog(@"%d",metre);
}
- (void (^)(int))run
{
return ^(int meter){
NSLog(@"跑了%d米",meter);
};
}
-(void)eat2:(BlockName)block{
block();
}
@end
//viewcontroller
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@property (nonatomic, strong) Person *p;
@end
@implementation ViewController
//block作为方法返回值(代码在内部,调用在外部)
- (void)block3
{
Person *p = [[Person alloc] init];
[p run:2];
//注意理解;p.run等价于[p run];
//注意这两种调用结果一样,第二种是第一种的实现过程
p.run(2);//调用方法:非常牛逼!!!!
void(^run)(int) = p.run;
run(2);
//虽然p.run返回的是一个void(^)(int)类型的block,但这样写也对void(^run)(),没写参数就是参数都为0,run()就是传入参数为0
void(^run2)() = p.run;
run2();
}
//block作为方法参数(外部传代码,调用在内部)
- (void)block2
{
Person *p = [[Person alloc] init];
void(^block)() = ^{
NSLog(@"吃东西");
};
[p eat:block];
[p eat2:block];
// 传入block给参数的Block赋值
[p eat:^{
NSLog(@"吃东西");
}];
//该block实现可以没有block返回类型:NSString *,但有更规范
[p eat3:^NSString *(int a) {
return [NSString stringWithFormat:@"该block实现中有返回值类型NSString,传入参数为:%zd",a];
}];
}
//block作为属性(保存一段代码到对象中)
- (void)block1
{
Person *p = [[Person alloc] init];
void(^block)() = ^() {
NSLog(@"执行对象中block");
};
p.operation = block;
p.operation = ^(){
NSLog(@"执行对象中block");
};
_p = p;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//执行对象中保存的block
_p.operation();
}
@end