iOS __attribute__
iOS __attribute__
最近在逛博客的过程中看到__attribute__的例子,就整理了一下,自己动手尝试了几个比较常用的。
对于__attribute__网上是这么解释的:
Clang Attributes是Clang提供的一种源码注解,方便开发者向编译器表达某种要求,参与控制如Static Analyzer、Name Mangling、Code Generation等过程,一般以attribute(xxx)的形式出现在代码中;为方便使用,一些常用属性也被Cocoa定义成宏,比如在系统头文件中经常出现的NS_CLASS_AVAILABLE_IOS(9_0)就是attribute(availability(...))这个属性的简单写法。
下面来看例子
1 __attribute__((objc_subclassing_restricted))
restricted是受限制的意思,表示这个类不能被继承,它修饰在一个类的头文件中


我写了一个类表示狗,一个表示猫,继承的时候就会报错
2 __attribute__((objc_requires_super))
这个修饰在方法之后,表示子类重写这个方法须调用父类的方法,否则会给警告,我们用小狗来演示



我们可以看到调用super后警告就会消失
3__attribute__((objc_runtime_name("wolf")))
这个表示可以修改一个类的isa指针,用于 @interface 或 @protocol,将类或协议的名字在编译时指定成另一个,代码混淆用它再好不过了


我们对ClangAttributeCat类做了标记,可以看到在运行时类的名字做了改变
4 __attribute__((deprecated("str")))
方法警告提示,修饰在方法或属性的后面,在调用的时候会给出警告提示,str是我们警告的内容


例子很简单不多说
5 NS_UNAVAILABLE
禁止使用标识,也是修士在属性和方法的后面,标识禁止使用。
NS_UNAVAILABLE是一个宏定义,点击进入后可以看见
#define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE
UNAVAILABLE_ATTRIBUTE也是一个宏定义,我们可以直接使用两个作用是一样的,进入宏定义后我们又会发现
#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
最终还是用的__attribute__((unavailable)),所以例子也很简单,unavailable后面可以加提示。


6 __attribute__((constructor))/__attribute__((destructor))
构造解析器,修饰的方法可以再main方法前后分别运行,注意的是constructor 和 +load 都是在 main 函数执行前调用,但 +load 比 constructor 更加早一点,因为 dyld(动态链接器,程序的最初起点)在加载 image(可以理解成 Mach-O 文件)时会先通知 objc runtime 去加载其中所有的类,每加载一个类时,它的 +load 随之调用,全部加载完成后,dyld 才会调用这个 image 中所有的 constructor 方法。
构造器修饰的方法不一定要写在main的文件里,也可以在其他的文件里。
修饰的方法不一定是一个,也可以多个。


我们可以看到运行结果load->beforeMain->main->afterMain,在上面的main方法里我把autoreleasepool里面的都注释掉了,是因为它会启动runloop循环,导致main方法不能运行完毕,afterMain就不能运行,这里为了演示所以注释掉,所以开发中__attribute__((destructor))用不到。
7 __attribute__ enable_if
参数静态检查,这个属性只能用在 C 函数上,修士在方法后面,检查参数是否正确,错误会编译不通过。
对于这个我还是有点疑惑,enable_if后面的字符串我一直没搞明白是干什么的,这里就填空字符串吧。


8 __attribute__((overloadable))
用于C函数,修饰同名不同参数的方法,可以同时存在,调用时只需传递不同的参数

调用:
overLoad("helloworld");
overLoad(10);
overLoad(YES);
9 __attribute__((cleanup()))
声明栈中的一个变量,当变量的作用域结束后,调用cleanup里的方法。
这里我们来定义三个变量NSString,int,block


在结尾的输出中,顺序是按照block->int->NSString的顺序,这也符合栈后进先出的原则。
10 __attribute__((NSObject))
参照网上的说法会把一个非OC对象的内存管理,当做OC对象来管理。如果没看懂我们来看例子

看第14行我们用typedef重新定义了CFDictionaryRef,在这里为了体现内存管理,我们写了两个属性cfDictionaryStrong、cfDictionaryWeak,分别用strong、weak修饰。
如果按照正常的逻辑在viewDidLoad里面设值,cfDictionaryStrong会保留。

如上图,在viewDidLoad里设值,点击的时候打印,我们看到cfDictionaryStrong打印出结果,cfDictionaryWeak为空。
11 __attribute__((nonnull))
这个修饰在方法的后面,表示方法的参数不能为nil,如果调用参数为nil会发出警告,太简单了不写例子了。
最后笔者第一次写简书,希望大家多多支持-.-