专注iOS开发(OC/Swift)

__attribute__ 高级运用

2018-08-22  本文已影响13人  洲洲哥

本文首发地址

__attribute__((cleanup(...))),用于修饰一个变量(对象),在它的作用域结束时可以自动执行一个指定的方法

例如:

基本用法

1:对于Class对象

// 指定一个cleanup方法,注意入参是所修饰变量的地址,类型要一样
// 对于指向objc对象的指针(id *),如果不强制声明__strong默认是__autoreleasing,造成类型不匹配

// 加了个`unused`的attribute用来消除`unused variable`的warning


static void ZZGCleanUp(__strong ZZG **zzg) {
    NSLog(@"%@",*zzg);
}

{
// 调用
__strong Sark *sark __attribute__((cleanup(ZZGCleanUp),unused)) = [ZZG new];
}
// 当运行到这个作用域结束时,自动调用ZZGCleanUp

2:对于NSString对象


static void stringCleanUp(__strong NSString **string) {
    NSLog(@"%@", *string);
}


{
    __strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"ZZG";
} // 当运行到这个作用域结束时,自动调用stringCleanUp

高级用法

1:既然__attribute__((cleanup(...)))可以用来修饰变量,block当然也是其中之一
一块搞一个block

// void(^block)(void)的指针是void(^*block)(void)

static void blockCleanUp(__strong void(^*block)(void)) {
    (*block)();
}

于是在一个作用域里声明一个block:
{
    __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^{
        NSLog(@"block.......");
    };
} // 这里输出"block......."

2:写一个实例如下

2.1:创建一个AttributeLock

.h中如下定义

typedef void (^zzg_cleanupBlock_t)(void);
static inline void zzg_executeCleanupBlock (__strong zzg_cleanupBlock_t *block) {
    (*block)();
}

// 该对象在代码段释放前调用的函数
#define attributeExit\
      __strong void(^block)(void) __attribute__ ((cleanup(zzg_executeCleanupBlock),unused)) = ^

#import <Foundation/Foundation.h>
@interface AttributeLock : NSObject
-(void)start;
-(void)stop;
@end

.m如如下

#import "AttributeLock.h"

@implementation AttributeLock
1. -(void)dealloc {
    NSLog(@"---dealloc");
    
}
-(void)start {
    NSLog(@">>>>>>>start");
}
-(void)stop {
    NSLog(@"<<<<<<stop");
}
@end

2.2:调用如下

AttributeLock * loc = [[AttributeLock alloc] init];
    [loc start];
    // *** 该方法可以放在任何位置
    attributeExit {
        NSLog(@"===========exit");
    };
    
    [loc stop];

2.3:打印如下

2018-08-22 20:16:18.524553+0800 POSPay[83808:9075309] >>>>>>>start
2018-08-22 20:16:18.524708+0800 POSPay[83808:9075309] <<<<<<stop
2018-08-22 20:16:18.524923+0800 POSPay[83808:9075309] ===========exit
2018-08-22 20:16:18.525214+0800 POSPay[83808:9075309] ---dealloc

可以看出在dealloc之前调用该方法

总结ps:

1* 作用域结束时可以自动执行一个指定的方法

2* 指定一个cleanup方法,要注意传入的参数修饰变量的地址,并且类型要一样。并且对于指向Objc对象的指针(id *),如果不强制声明__strong 默认是__autoreleasing,造成类型不匹配

3* 只有在作用域结束时会自动调用cleanup中的方法

4* 如果一个作用域内有若干个cleanup的变量,他们的调用顺序是先入后出的栈式顺序。而且,cleanup是优先于这个对象的dealloc调用

有些地方说的不到位,还请各位看官指正。。。

可以来微信公众号(洲洲哥)后台给我们留言。 快来扫码关注我们吧!

公众号二维码
上一篇下一篇

猜你喜欢

热点阅读