【Objective_C学习笔记】Block的使用

  • Block的介绍
  1. 用于对象之间的通信,通信方式是1对1;
  2. 是一个匿名的函数代码块,此代码块可以作为参数传递给其他对象;
  3. 可以把block当做Objective-C的匿名函数,block是OC中的一种数据类型,^是block的特有标记。
  • Block的格式
(返回类型)(^block名称)(参数类型)=^(参数列表){代码实现};。

  说明:如果没有参数,等号后面参数列表的()可以省略。

 

  • Block 的使用
  1. Block的定义
- (void)viewDidLoad {
    [super viewDidLoad];
    //1、无参数、无返回值的block的定义和使用
    void (^myBlock1)() = ^{
        NSLog(@"block无返回值,无参数");
    };
    myBlock1();
    
    //2、无参数、有返回值的block的定义和使用
    int (^myBlock2)() = ^{
        return 10;
    };
    NSLog(@"myBlock2的返回值是%d", myBlock2());
    
    //3、有参数,有返回值的block定义和使用
    int (^myBlock3)(int, int) = ^(int a, int b) {
        return a + b;
    };
    NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8));
    
}

  运行结果:

    2.  Block作为方法的参数

        将block作为方法的参数,可以用block来封装代码块。

- (void)viewDidLoad {
    [super viewDidLoad];
    //1、无参数、无返回值的block的定义和使用
    void (^myBlock1)() = ^{
        NSLog(@"block无返回值,无参数");
    };
    myBlock1();
    
    //2、无参数、有返回值的block的定义和使用
    int (^myBlock2)() = ^{
        return 10;
    };
    NSLog(@"myBlock2的返回值是%d", myBlock2());
    
    //3、有参数,有返回值的block定义和使用
    int (^myBlock3)(int, int) = ^(int a, int b) {
        return a + b;
    };
    NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8));
    
    //4、作为方法的参数,可以用block来封装代码块。
    [self testBlockAsParam:^{
        NSLog(@"block作为testBlockAsParam的参数");
    }];
}

- (void) testBlockAsParam: (void (^)()) block {
    block(); //执行block内部代码
}

 运行结果:

 3.  Block作为属性

      block作为属性,应使用copy修饰。若用weak、assign修饰block属性时,当block所在函数\方法返回\结束,该block就会被销毁。在其他方法内部调用访问该block,就会引发野指针错误EXC_BAD_ACCESS

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,copy) void (^myBlock)(); //block作为属性
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //1、无参数、无返回值的block的定义和使用
    void (^myBlock1)() = ^{
        NSLog(@"block无返回值,无参数");
    };
    myBlock1();
    
    //2、无参数、有返回值的block的定义和使用
    int (^myBlock2)() = ^{
        return 10;
    };
    NSLog(@"myBlock2的返回值是%d", myBlock2());
    
    //3、有参数,有返回值的block定义和使用
    int (^myBlock3)(int, int) = ^(int a, int b) {
        return a + b;
    };
    NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8));
    
    //4、block作为方法的参数,可以用来封装代码块。
    [self testBlockAsParam:^{
        NSLog(@"block作为testBlockAsParam的参数");
    }];
    
    //5、block作为属性
    
    [self setMyBlock:^{
        NSLog(@"block作为属性");
    }];
    NSLog(@"%@",self.myBlock);
    self.myBlock();//block作为属性的调用
}

- (void) testBlockAsParam: (void (^)()) block {
    block(); //执行block内部代码
}
View Code

     运行结果:

 4. Block 访问外部变量

  • block内部可以访问外部的变量,block默认是将其复制到其数据结构中来实现访问的。
  • 默认情况下,block内部不能修改外面的局部变量,因为通过block进行闭包的变量是const的。
  • 给局部变量加上__block关键字,这个局部变量就可以在block内部修改,block是复制其引用地址来实现访问的。
#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,copy) void (^myBlock)(); //block作为属性
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //1、无参数、无返回值的block的定义和使用
    void (^myBlock1)() = ^{
        NSLog(@"block无返回值,无参数");
    };
    myBlock1();
    
    //2、无参数、有返回值的block的定义和使用
    int (^myBlock2)() = ^{
        return 10;
    };
    NSLog(@"myBlock2的返回值是%d", myBlock2());
    
    //3、有参数,有返回值的block定义和使用
    int (^myBlock3)(int, int) = ^(int a, int b) {
        return a + b;
    };
    NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8));
    
    //4、block作为方法的参数,可以用来封装代码块。
    [self testBlockAsParam:^{
        NSLog(@"block作为testBlockAsParam的参数");
    }];
    
    //5、block作为属性
    
    [self setMyBlock:^{
        NSLog(@"block作为属性");
    }];
    NSLog(@"%@",self.myBlock);
    self.myBlock();//block作为属性的调用
    
    //6、访问外部变量
    //block直接访问外部变量 默认是将其复制到其数据结构中来实现访问的,但是不能更改这变量的值,因为在block中这变量是const类型。
    //对于访问用__block修饰的外部变量,block内是复制其地址实现访问的,block内可以修改变量的值。
    
    int a = 5;
    __block int b = 10;
    NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b);
    
    void (^myBlock4)() = ^{
        b = 15;
       NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b);
    };
    myBlock4();
    NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b);
}

- (void) testBlockAsParam: (void (^)()) block {
    block(); //执行block内部代码
}
View Code

运行结果:

ps:目前知道的就是这些,欢迎补充

posted @ 2015-11-30 18:28  风语菡  阅读(395)  评论(0编辑  收藏  举报