理解ReactiveCocoa的@onExit宏

onExit的用法是这样的:

- (void)exitTest {
    @onExit {
        NSLog(@"1");
    };
    {
        @onExit {
            NSLog(@"2");
        };
        
        {
            @onExit {
                NSLog(@"3");
            };
        }
    }
    @onExit {
        NSLog(@"4");
    };
}

就是和Swift的defer用法一样,在离开作用域的时候执行大括号里的代码。注意,同一个作用域下,后定义的@onExit先执行。
具体的定义如下:

#define onExit \
    rac_keywordify \
    __strong rac_cleanupBlock_t metamacro_concat(rac_exitBlock_, __LINE__) __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^

整体的宏结构和我们熟悉的@weakify,@strongify是一致的。
对于

    @onExit {
        NSLog(@"1");
    };

宏展开之后就是:


        __strong rac_cleanupBlock_t rac_exitBlock_xxxx __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^ {
            NSLog(@"1");
        };

其中rac_exitBlock_xxxx中的xxxx部分是当前的行号。
这句话的意思就是定义了一个叫rac_exitBlock_xxxx的变量,它是一个block,block的内容就是我们写的代码块了。
这里的关键是一个Clang编译器的修饰符attribute((cleanup(function)))。这个修饰符的作用是:被修饰变量在离开作用域的时候,执行其中指定的function,执行function的时候会把被修饰的变量的指针作为function的参数传递过去。
这样解析可能还是懵懵懂懂的。
看看具体的细节吧

typedef void (^rac_cleanupBlock_t)();

static inline void rac_executeCleanupBlock (__strong rac_cleanupBlock_t *block) {
    (*block)();
}

ReactiveCocoa使用attribute((cleanup(function)))这个修饰符的时候,给的function是rac_executeCleanupBlock,这个function的就是执行传进来的这个block。
( ⊙ o ⊙ )啊!传进来的这个block不就正式我们写的代码块了嘛!
于是,这个特性的作用就是:在作用域结束的时候调用我们的代码块!

你可能感兴趣的:(理解ReactiveCocoa的@onExit宏)