理解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不就正式我們寫的代碼塊了嘛!
于是,這個特性的作用就是:在作用域結束的時候調用我們的代碼塊!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容