• __attribute__ 高级运用


    __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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2:对于NSString对象

    
    static void stringCleanUp(__strong NSString **string) {
        NSLog(@"%@", *string);
    }
    
    
    {
        __strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"ZZG";
    } // 当运行到这个作用域结束时,自动调用stringCleanUp
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    高级用法

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

    // void(^block)(void)的指针是void(^*block)(void)
    
    static void blockCleanUp(__strong void(^*block)(void)) {
        (*block)();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    
    于是在一个作用域里声明一个block:
    {
        __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^{
            NSLog(@"block.......");
        };
    } // 这里输出"block......."
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    .m如如下

    #import "AttributeLock.h"
    
    @implementation AttributeLock
    1. -(void)dealloc {
        NSLog(@"---dealloc");
        
    }
    -(void)start {
        NSLog(@">>>>>>>start");
    }
    -(void)stop {
        NSLog(@"<<<<<<stop");
    }
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.2:调用如下

    AttributeLock * loc = [[AttributeLock alloc] init];
        [loc start];
        // *** 该方法可以放在任何位置
        attributeExit {
            NSLog(@"===========exit");
        };
        
        [loc stop];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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
    
    • 1
    • 2
    • 3
    • 4

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

    总结ps:

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

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

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

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

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

    • 欢迎各位一块学习,提高逼格!
    • 也可以添加洲洲哥的微信公众号

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

    维系公众号

  • 相关阅读:
    2000-2021年全国各省水土流失治理面积数据
    什么是架构?
    李开复创业公司零一万物开源迄今为止最长上下文大模型:Yi-6B和Yi-34B,支持200K超长上下文
    03【深度学习】YOLOV3-WIN11环境搭建(配置+训练)
    学习笔记:如何在 Vue 项目中使用 MQTT
    对产品实现汇率换算服务(将两个CompletableFuture对象整合起来,无论它们是否存在依赖)
    数据结构四:线性表之带头结点的单向循环循环链表的设计
    dataFEED OPC Suite V5.20轻松应对Windows DCOM安全更新
    Go栈内存管理源码解读
    C++11 列表初始化都做了什么?
  • 原文地址:https://blog.csdn.net/whuizhou/article/details/125418052