iOS-黑魔法

2020-06-08  本文已影响0人  JerrySi

最近项目中一直用到OC的代码,有必要把常用的当时平常又不是很在意的黑魔法再列举下。

attribute((cleanup))

用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法

static void blockCleanUp(__strong void(^*block)(void)) {
    (*block)();
}
#define onExit \
    __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    onExit {
       NSLog(@"2");
    };
    NSLog(@"1");
}

used

used的作用是告诉编译器,我声明的这个符号是需要保留的。被used修饰以后,意味着即使函数没有被引用,在Release下也不会被优化。如果不加这个修饰,那么Release环境链接器会去掉没有被引用的段。
冷启动优化:Clang 提供了很多的编译器函数,它们可以完成不同的功能。其中一种就是 section() 函数,section()函数提供了二进制段的读写能力,它可以将一些编译期就可以确定的常量写入数据段。 在具体的实现中,主要分为编译期和运行时两个部分。在编译期,编译器会将标记了 attribute((section())) 的数据写到指定的数据段中,例如写一个{key(key代表不同的启动阶段), *pointer}对到数据段。到运行时,在合适的时间节点,在根据key读取出函数指针,完成函数的调用。

#define RAM_FUNCTIONNAME_EXPORT __attribute__((used, section("__RAM, __funcName"))) \
static const char *__ram_funcName__ = __func__

#pragma mark - 实现存储字符串
struct RAM_String {
    __unsafe_unretained NSObject *key;
    __unsafe_unretained NSObject *value;
};
/// id 参数,在同一个.m文件中调用此宏需要id唯一
#define RAM_STRINGS_EXPORT(key, value, id) __attribute__((used, section("__RAM,__ram.data"))) \
static const struct RAM_String __S##id= (struct RAM_String){key, value};

#pragma mark - 实现存储block
struct RAM_Block {
    char *key;
    __unsafe_unretained void (^block)(void);
};

#define RAM_BLOCKS_EXPORT(key, block) __attribute__((used, section("__RAM," "__"#key ".block"))) \
static const struct RAM_Block __B##key = (struct RAM_Block){((char *)&#key), block};

#pragma mark - 实现存储方法
struct RAM_Function {
    char *key;
    void (*function)(void);
};

#define RAM_FUNCTION_EXPORT(key) \
static void _ram##key(void); \
__attribute__((used, section("__RAM," "__"#key ".func"))) \
static const struct RAM_Function __F##key = (struct RAM_Function){(char *)(&#key), (void *)(&_ram##key)}; \
static void _ram##key \

参考:https://www.jianshu.com/p/33663906f7a2

objc_runtime_name

用于 @interface 或 @protocol,将类或协议的名字在编译时指定成另一个,这个属性可以用来做代码混淆

 __attribute__((objc_runtime_name("OtherTest")))
 @interface Test : NSObject
 @end
 
 NSLog(@"%@", NSStringFromClass([Test class])); // "OtherTest"
上一篇下一篇

猜你喜欢

热点阅读