美文网首页
Block深入浅出 (一)

Block深入浅出 (一)

作者: 苍天兄弟 | 来源:发表于2019-01-14 15:23 被阅读0次

    一 概述

    闭包就是1个函数或指向函数的指针+该函数的执行的上下文变量(也就是自由变量),Block是OC对于闭包的实现。其中Block可以定义在方法的内部或外部,其本质是对象,作用是使代码高聚合,只有调用Block的时候,才会调用代码块里的内容。

    使用clang将OC代码转换为C++文件查看block的方法:

    • 在命令行输入代码 clang -rewrite-objc 需要编译的OC的.m文件(如果这步报错找不到UIKit,就是用这个命令生成 clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk 需要编译的OC的.m)
    • 这时查看当前的文件夹里 多了一个相同名称的 .cpp文件,可以在命令行输入 open 生成的.cpp 查看文件

    开发中常用typedef定义一个block
    void(^myBlock)(void);
    使用时直接

    @property (nonatomic, copy) myBlock blk;
    self.blk = ^(){
            NSLog(@"typedef定义的block");
     };
    

    定义一个无参数无返回值的block

    void(^myBlock1)(void) = ^(){
            NSLog(@"我是无参无返回值block");
     };
    

    定义一个有参数无返回值的block

    void(^myBlock2)(NSString* string) = ^(NSString* string) {
            NSLog(@"我是有参数无返回值block");
     };
    

    定义一个有参数有返回值的block

    NSString*(^myBlock3)(NSString* string) = ^(NSString* string){
            return [string stringByAppendingString:@"我是有参数有返回值的block"];
     };
    

    二 Block与外部变量

    截取局部变量的值
    • 默认情况下,对于block外的变量引用,block是将其值复制到block内部的结构体中来访问的,也就是说block的自动变量的截取只针对block块内部使用的自动变量,不使用则不截取。特别注意默认情况下block只能访问不能修改局部变量的值。
       int a = 10;
        void(^myBlock)(void) = ^{
            NSLog(@"a的值是%d",a);
        };
        a = 20;
        myBlock();
    

    输出结果为a=10,因为在a = 20赋值之前,a=10的值被截取到了block内部,a不管外部怎么变化,block内部的a永远都为10。

    使用__block修饰的外部变量

    对于用__block修饰的外部变量的引用,block是复制其引用地址来实现访问的,所以block内部可以修改__block修饰的外部变量的值。

        __block int a = 10;
        void(^myBlock)(void) = ^{
            NSLog(@"a的值是%d",a);
        };
        a = 20;
        myBlock();
    

    输出结果为a=20
    为什么__block修饰的外部变量的值就可以在block内部修改呢?
    我们使用clang 将这个.m文件转成 .cpp查看一下

    __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};
        void(*myBlock)(void) = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
        (a.__forwarding->a) = 20;
    

    发现局部变量a变成了__Block_byref_a_0结构体类型的自动变量实例

    相关文章

      网友评论

          本文标题:Block深入浅出 (一)

          本文链接:https://www.haomeiwen.com/subject/gnmddqtx.html