1、如果想限制方法里必须调用用父类方法
__attribute__((objc_requires_super));
NS_REQUIRES_SUPER
__attribute__((objc_subclassing_restricted)) @interface Eunuch : NSObject @end @interface Child : Eunuch // <--- Compile Error @end
3、在main函数前、后注入代码
__attribute__((constructor)) static void beforeMain(void) { NSLog(@"beforeMain"); } __attribute__((destructor)) static void afterMain(void) { NSLog(@"afterMain"); } int main(int argc, const char * argv[]) { NSLog(@"main"); return 0; }constructor 和
+load
都是在 main 函数执行前调用,但
+load
比 constructor 更加早一丢丢,因为 dyld(动态链接器,程序的最初起点)在加载 image(可以理解成 Mach-O 文件)时会先通知
objc runtime
去加载其中所有的类,每加载一个类时,它的
+load
随之调用,全部加载完成后,dyld 才会调用这个 image 中所有的 constructor 方法。
4、在作用域结束时注入代码
// 指定一个cleanup方法,注意入参是所修饰变量的地址,类型要一样 // 对于指向objc对象的指针(id *),如果不强制声明__strong默认是__autoreleasing,造成类型不匹配 static void stringCleanUp(__strong NSString **string) { NSLog(@"%@", *string); } // 在某个方法中: { __strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"sunnyxx"; } // 当运行到这个作用域结束时,自动调用stringCleanUp
Block也是变量,因此可以:
// void(^block)(void)的指针是void(^*block)(void) static void blockCleanUp(__strong void(^*block)(void)) { (*block)(); }
通过定义一个宏{ // 加了个`unused`的attribute用来消除`unused variable`的warning __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^{ NSLog(@"I'm dying..."); }; } // 这里输出"I'm dying..."
#define onExit\ __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^这样就可以
onExit { //somecode here };