Block的详细使用(五)

2017-12-11  本文已影响11人  凉白开0072

Block 的初步理解

  1. 例如定义一个block:void(^myblock)(int);=>与int a;比较
  2. block的类型:void(^)(int);=>等价于int
  3. block的变量名:myblock=>等价于a
  4. 注意:
    1. 定义block时若有输入参数(本例为int),参数名可有(int x)可无(int)但必须有参数的类型,但实现是必须有参数的类型和变量名.
    2. 实现block时,也可以将block返回类型写在实现中(通常不写),写在仅仅挨着^后面,不需要(),这样有利于让实现者知道该block返回什么值,(其实这样写更加规范,苹果官方有使用:当带有返回值的block作为一个方法的参数时,当调用这个方法时,系统的提示代码在block实现中会加上返回类型,具体看典例)
 //实现中写返回参数类型
    NSString *(^myblockx)(int) = ^NSString *(int a){
        return @"";
    };
    //实现中不写返回参数类型
    NSString *(^myblockx2)(int) = ^(int a){
        return @"";
    };

定义一个block

  1. 无返回值有参数

     //定义一个block变量,然后给这个变量赋值:myblock
    //此时void(^)(int)为类型名,myblock1为变量名
    //int a ; a = 3;
    void(^myblock1)(int);
    myblock1 = ^(int a){
    };
    //定义一个block变量并赋值//int a = 3;
    void(^myblock2)(int) = ^(int a){
    };
    
  2. 无返回值无参数

      //1.先定义,在赋值
    void(^myblock0)();
    myblock0 = ^{
    };
    //2.定义时赋值(略)
    
  3. 有返回值无参数

     //1.先定义,在赋值(略)
    //2.定义时赋值
    int(^myblock4)()=^{
        return 3;
    };
    
  4. 有返回值有参数且参数(注意参数中可以有变量名也可以没有变量名,变量名与实现时参数的变量名无关联)

     //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;
    };
    
    
  5. 参数为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类

  1. 面向对象思想:将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的常见使用

  1. block成为属性
    1. 举例:

      @property (nonatomic, strong) void(^operation)();
      @property (nonatomic, strong) NSString *operation;
      
    2. 作用: 把block保存到对象中,恰当时机的时候才去调用

    3. 注意:这里容易引发循环引用,引起原因前面讲过,如何解决(weakself),不再赘述.

  2. block成为方法参数:传入一个block参数
    1. 举例:

        - (void)eat:(void(^)(int))block;
      - (void)eat:(nsstring *)block;
      
    2. 作用: 把block当做方法的参数使用,外界不调用,都是方法内部去调用,Block实现交给外界决定.(注意理解)

  3. 成为返回参数:该方法返回一个block
    1. 举例:

      - (void(^)(int))run;
      -(nsstring *)run;
      
    2. 作用:把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
上一篇下一篇

猜你喜欢

热点阅读