让 OC (Objective-C) 支持 defer

swift 里面的 defer 可真是太好用,可是 OC 有时候也是不得不用的,写就写吧,可是当我需要 defer 的时候 OC 却没有,这总让人有些不得劲儿

比如下面这样

    uint8_t *cmpResult = malloc(capacity); // 申请内存

    int cmpCode = someCFunction(cmpResult) // 调用 C 函数
    if (cmpCode != 0) {
        free(cmpResult); // 释放内存
        return nil;
    }
    if (...) {
        free(cmpResult); // 释放内存
        return nil;
    }
    
    NSData *resultData = [NSData dataWithBytes:cmpResult length:cmpImageSize];
    free(cmpResult); // 释放内存
    return resultData;

这要求我们写代码必须要仔细认真,在申请完内存后处理好流程中的每一处分支,每一处分支都必须 有且仅有 有且仅有 有且仅有 一次调用 free(cmpResult); 来释放内存

幸运的是,OC 还真有办法,能实现 defer 功能,上面的代码就可以简化得清晰明了

    __block uint8_t *cmpResult = malloc(capacity); // 申请内存
    @defer {
        // 紧跟着申请完的内存,马上在 defer 里面释放
        free(cmpResult);
    };

    // 后面完全不考虑内存释放的事情
    // 把后面的所有的 free(cmpResult); 都删掉

实现方法呢,来自于这篇文章 《 如何在 Objective-C 的环境下实现 defer 》,原理和细节里面也讲得很清楚,我就不像复读机一样制造垃圾了

这里提供一下我实现 defer 的代码,放在一个 .h 头文件里就可以用了

// GG_defer.h
#ifndef GG_defer_h
#define GG_defer_h

#define gg_concat(A, B) gg_concat_(A, B)
#define gg_concat_(A, B) A ## B
#define defer \
    autoreleasepool {} \
    __strong ext_cleanupBlock_t gg_concat(ext_exitBlock_, __LINE__) __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^

typedef void (^ext_cleanupBlock_t)(void);
void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block) {
    (*block)();
}

#endif /* defer_h */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容