原文地址http://blog.sunnyxx.com/2014/09/15/objc-attribute-cleanup/#rd。
关于__attribute__
的更详细的用法可以参考这一篇http://blog.csdn.net/ruixj/article/details/4274721。
__attribute__
是用于向编译器描述特殊的标识、检查或优化。下面通过介绍两个基本的用法:
1.__attribute__
((cleanup(…))),用于修饰一个变量,在它的作用域结束之后可以自动执行一个指定的方法,如:
// 传入的参数是所修饰的变量的指针的地址
static void stringCleanUp(__strong NSString **string) {
NSLog(@"%@",*string);
}
// 在某个方法中
{
__strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"Mr_C";
}//当运行到这个作用域结束时,自动调用stringCleanUp
所谓的作用域结束包括大括号、return、goto、break、exception等各种情况。(当然可以修饰的不仅是string还有自定义的class和基本类型)。
需要注意的是当一个作用域内有多个cleanup变量,那么先修饰的要后执行,调用顺序是先入后出的栈式顺序。而且cleanup是先于这个对象的dealloc调用的。
进阶用法:
使用__attribute__((cleanup()))
修饰block
可以实现通过宏定义让代码片段成对的出现,但是执行顺序缺可以是无序的状态。
//先简单定义一个block
static void blockCleanUp(__strong void(^*block)(void)) {
*block();//回调执行了该block
}
在作用域内声明了一个block:
{
//加了个`unused`的attribute来消除`unused variable`的warning
__strong void(^block)(void) __attribute__((cleanup(blockCleanUp),unused)) = ^{
NSLog(@"I'm dying...");
};
}// 这里输出"I'm dying..."
在Reactive Cocoa
中神奇的@onExit
方法,其实正是上面的写法,简单定义个宏:
#define onExit\
__strong void(^block)(void) __attribute__((cleanup(blockCleanUp),unused)) = ^
用这个宏就能将一段写在前面的代码最后执行:
{
onExit {
NSLog(@"test");
};
}//输出"test"
示例:
NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
//这里有无数行代码
//
//
[aLock unlock];//看到这早已忘了和哪个lock对应了
用了onExit
之后代码更集中了:
NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
onExit {
[aLock unlock];//这时无论改行代码在哪里执行都无所谓了
}
2 . __attribute__
((objc_requires_super))强制子类在override一个方法的时候必须调用super。
@interface MiniEastNorth :NSObject
-(void)dateWithGirl __attribute__((objc_requires_super));
@end
等价于定义好的一个Macro:NS_REQUIRES_SUPER加了这个属性之后子类没调用super编译器是无法通过的。