cleanup,OC中的 defer

在 Swift 中有个强大的语法 defer,可以在作用域结束的时候执行一段代码。对于一些需要在逻辑执行完成后做清理的情况来说非常简便;终于发现 OC 中可以通过 __attribute__ 编译说明实现这一功能

cleanup

cleanup 声明符的作用是修饰一个变量,在当前作用域结束时可以自动执行一个指定的方法;这儿的作用域通常就是函数调用出栈之前,那么函数执行完毕以及 returnbreakexception 等中断执行的情况都会触发

修饰变量

1
2
3
4
5
6
7
8
9
10
static void cleanUpFunction(NSString **val) {
NSLog(@"%@ cleanup", *val);
}

- (void)testFunc {
NSString *string __attribute__((cleanup(cleanUpFunction))) = @"testString";
NSLog(@"%@ used", string);
}

// result: "testString used" --> "testString cleanup"

cleanup & dealloc

cleanup 声明的方法会在类的 dealloc 方法之前调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@interface DemoClass : NSObject
@end
@implementation DemoClass
- (void)dealloc {
NSLog(@"Demo class dealloc");
}
@end

static void demoClassCleanup(DemoClass **demo) {
NSLog(@"demo class %@ cleanup", *demo);
}

- (void)test {
DemoClass *demo __attribute__((cleanup(demoClassCleanup))) = [[DemoClass alloc] init];
NSLog(@"%@", demo);
}

// result: <DemoClass: 0x600000ee0570> --> demo class <DemoClass: 0x600000ee0570> cleanup --> Demo class dealloc

如果作用域内有多个 cleanup 声明的变量,cleanup 的调用顺序与变量的销毁顺序一致,符合调用栈后进先出的规律

cleanup block == defer

Block 也是变量,所以同样可以用 cleanup 来修饰;通常一个没有返回值没有参数的 Block 的类型声明为 void(^)(void),它的指针就是 void(^*)(void)

因此可以将 Block 清理函数声明为

1
2
3
static void _blockCleanup(void (^*block)(void)) {
(*block)();
}

使用的时候同样对 Block 变量赋值即可

1
2
3
4
5
void test() {
void(^block)(void) __attribute__((cleanup(_blockCleanup), unused)) = ^{
NSLog(@"block executed");
};
}

将使用时对 Block 变量赋值的操作定义为宏就可以得到 defer 语法糖了

1
2
3
4
5
6
7
#define defer void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

void test() {
defer {
NSLog(@"block executed");
};
}
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2017-2021 HonQi

请我喝杯咖啡吧~