iOS开发 __attribute__

作者: 本本的开心牧场 | 来源:发表于2018-06-12 10:55 被阅读63次

    attribute是一套编译器指令,被GNU和LLVM编译器所支持,允许对于attribute增加一些参数,做一些高级检查和优化。
    attribute的语法是,在后面加两个括号,然后写属性列表,属性列表以逗号分隔。在iOS中,很多例如NS_CLASS_AVAILABLE_IOS的宏定义,内部也是通过attribute实现的。

    __attribute__((attribute1, attribute2));
    

    objc_subclassing_restricted

    objc_subclassing_restricted属性表示被修饰的类不能被其他类继承,否则会报下面的错误。

    错误信息:
    Cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute
    

    objc_requires_super

    objc_requires_super属性表示子类必须调用被修饰的方法super,否则报黄色警告。
    在一个方法中使用

    - (void)test __attribute__((objc_requires_super));`
    `警告信息:(不报错)
    Method possibly missing a [super test] call
    

    constructor / destructor

    constructor属性表示在main函数执行之前,可以执行一些操作。destructor属性表示在main函数执行之后做一些操作。constructor的执行时机是在所有load方法都执行完之后,才会执行所有constructor属性修饰的函数。

    __attribute__((constructor)) static void beforeMain() {
        NSLog(@"main函数执行前执行");
    }
    
    __attribute__((destructor)) static void afterMain() {
        NSLog(@"main函数执行后执行");
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSLog(@"main函数执行时执行");
        }
        return 0;
    }
    执行结果:
    debug-objc[23391:1143291] before main
    debug-objc[23391:1143291] execute main
    debug-objc[23391:1143291] after main
    

    在有多个constructor或destructor属性修饰的函数时,可以通过设置优先级来指定执行顺序。格式是attribute((constructor(1)))的方式,在属性后面直接跟优先级。

    __attribute__((constructor(3))) static void beforeMain3() {
        NSLog(@"after main 3");
    }
    
    __attribute__((constructor(1))) static void beforeMain1() {
        NSLog(@"after main 1");
    }
    
    __attribute__((constructor(2))) static void beforeMain2() {
        NSLog(@"after main 2");
    }
    

    在constructor中根据优先级越低,执行顺序越高。而destructor则相反,优先级越高则执行顺序越高。

    overloadable

    总所周知,oc中不像java,c++一样可以实现函数重载。overloadable属性允许定义多个同名但不同参数类型的函数,在调用时编译器会根据传入参数类型自动匹配函数。

    NSString * __attribute__((overloadable)) mytest(NSString *x) {return @"aa";}
    NSString * __attribute__((overloadable)) mytest(NSNumber *x) {return @"bb";}
    NSString * __attribute__((overloadable)) mytest(NSDictionary *x) {return @"cc";}
    NSString * __attribute__((overloadable)) mytest(int x) { return @"int"; }
    NSString * __attribute__((overloadable)) mytest(double x) { return @"double"; }
    NSString * __attribute__((overloadable)) mytest(long x) { return @"long"; }
    
      NSLog(@"%@",self.string);
        NSLog(@"%@",mytest(@(1)));
    

    objc_runtime_name

    objc_runtime_name属性可以在编译时,将Class或Protocol指定为另一个名字,并且新名字不受命名规范制约,可以以数字开头

    __attribute__((objc_runtime_name("123Object")))
    @interface Object : NSObject
    @end
    
    NSLog(@"%@", NSStringFromClass([self class]));
    
    执行结果:
    123Object
    

    这个属性可以用来做代码混淆,例如写一个宏定义,宏定义内部实现混淆逻辑。例如通过MD5对Object做混淆,32位的混淆结果就是497031794414a552435f90151ac3b54b,谁能看出来这是什么类。如果怕彩虹表匹配出来,再增加加盐逻辑。

    cleanup

    通过cleanup属性,可以指定给一个变量,当变量释放之前执行一个函数。指定的函数执行的时间,是在dealloc之前的。在指定的函数中,可以传入一个形参,参数就是cleanup修饰的变量,形参是一个地址。

    #import <Foundation/Foundation.h>
    static void releaseBefore(NSObject **object) {
        NSLog(@"%@", *object);
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
           NSObject *object __attribute__((cleanup(releaseBefore))) = [[NSObject alloc] init];
        }
        return 0;
    }
    

    如果遇到同一个代码块中,同时出现多个cleanup属性时,在代码块作用域结束时,会以添加的顺序进行调用

    unused

    还有一个属性很实用,在项目里经常会有未使用的变量,会报一个黄色警告。有时候可能会通过其他方式获取这个对象,所以不想出现这个警告,可以通过unused属性消除这个警告。

    NSObject *object __attribute__((unused)) = [[NSObject alloc] init];
    

    系统中已提供的一些方法
    在系统里也大量使用了attribute关键字,只不过系统不会直接在外部使用attribute,一般都是将其定义为宏定义,以宏定义的形式出现在外面。

    // NSLog
    FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2) NS_NO_TAIL_CALL;
    #define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
    
    // 必须调用父类的方法
    #define NS_REQUIRES_SUPER __attribute__((objc_requires_super))
    
    // 指定初始化方法,必须直接或间接调用修饰的方法
    #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
    

    相关文章

      网友评论

      本文标题:iOS开发 __attribute__

      本文链接:https://www.haomeiwen.com/subject/yrqleftx.html