前言

上一遍文章介绍了一些iOS体系自带的宏界说如NS_AVAILABLE_IOS(_ios)UNAVAILABLE_ATTRIBUTE,以及咱们平时在开发过程中怎样运用这些宏界说来写出更好的代码。可是这个宏界说背面的原理,履行流程却没有具体分析过,经过最近反复的查询材料和调研,现在来说说我理解下的这些宏界说背面的原理。下面就用UNAVAILABLE_ATTRIBUTE来举例。

一.宏界说UNAVAILABLE_ATTRIBUTE背面到底是什么?

点击检查一下体系文档,能够看到下面一段关于UNAVAILABLE_ATTRIBUTE的界说

/*
* only certain compilers support __attribute__((unavailable))
*/
#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
  #define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
#else
  #define UNAVAILABLE_ATTRIBUTE
#endif

这里阐明了UNAVAILABLE_ATTRIBUTE的界说是__attribute__((unavailable)),那么__attribute__((unavailable))又是什么呢?

解答: __attribute__机制 是GNU C 最好的特性之一,它不是规范的C语音,而是GCC中的一个扩展,只供GCC编译器运用的向源代码中注入语法的一种方法。它不是函数调用(虽然看起来挺像),咱们能够把它看成是向编译器供给关于它附加到的元素的附加信息,以答应编译器履行更多过错检查。作为iOS开发者可能对这个相对陌生,可是一些学习linux内核代码及一些开源软件的源码的程序员必定会经常看到 __attribute__ 的相关运用。

二. __attribute__怎样用?
1.关于 __attribute__ 书写格式

注意!__attribute__ 前后均有两个下划线,并且后面会紧跟2组小括号,括号里边是相关参数,如:

_attribute__((xxx))

举个比如,每一个oc项目肯定有一个main函数,假如我要在main里运用argv这个参数,而不运用argc这个参数,那么能够写成下面这样:

int main(int argc __attribute__((unused)) , char **argv)
{
    /* 运用 argv 但不运用 argc 的代码 */
}
2.关于 __attribute__ 有哪些参数

__attribute__能够设置函数特点(Function Attribute)、变量特点(Variable Attribute)和类型特点(Type Attribute),其各个特点的具体参数别离如下:

函数特点(Function Attribute) 变量特点(Variable Attribute) 类型特点(Type Attribute) Clang特有的
noreturn aligned aligned availability
noinline packed packed overloadable
always_inline transparent_union
pure unused
const deprecated
nothrow may_alias
sentinel
format
format_arg
no_instrument_function
section
constructor
destructor
used
unused
deprecated
weak
malloc
alias
warn_unused_result
nonnull

例如上面举例了表格里unused的运用,表示参数argc并没有用上,相似objc代码里的nullable。虽然这样写看起来很繁琐,但这些的写法既能让编译器消除正告,也能告知其他开发者这是成心这么设计的。当然删去实践不运用的变量会更好,可是某些场景下的确会有这种情况产生。

3.关于availability特点

看到这里,可能有些人有点疑惑,我第一点提到了UNAVAILABLE_ATTRIBUTE的界说是__attribute__((unavailable)),为啥这个表格里找不到unavailable呢?其实这是属于Clang特有的availability特点。

availability特点是一个后面紧跟小括号,括号里边以逗号为分隔的参数列表,第一个参数必须声明平台,现在支撑的平台是ios、macosx和watchos,有如下几个参数

availability参数 作用
introduced 声明第一次出现的版别
deprecated 声明要抛弃的版别,可再用,但在编译时会报过期正告
obsoleted 声明要移除的版别,不可再用
unavailable 声明函数不可用
message 能够阐明一些关于抛弃和移除的额外信息,编译时报正告会供给这些信息

而将这些参数与availability结合起来,便是一个具体的特性声明,因此availability的声明能够说是程碑式的。代码举个比如:

- (void)method __attribute__((availability(ios,introduced=3_0,deprecated=7_0,message="只引荐iOS体系3-7运用")));

除此之外,苹果官方也有自己界说的一些宏,便利开发者直接运用,展开后也是和上面的代码一样的,如:

- (void)method1 NS_DEPRECATED_IOS(3_0, 7_0,"只引荐iOS体系3-7运用");
- (void)method2 CF_DEPRECATED_IOS(3_0, 7_0,"只引荐iOS体系3-7运用");

其他更多常用的体系宏界说以及咱们应该怎样去运用能够移步我上一篇的文章:总结一下iOS体系的宏界说

三. 关于 __attribute__与非 GNU 编译器的兼容性

由于 __attribute__ 是 GNU C 特有的,如果在别的平台,是需求屏蔽的,也由于 __attribute__ 机制设计巧妙,如果在 GNU C 以外的平台上运用,能够经过判别是否GNU机器来决议是否引入 __attribute__ ,例如:

 #if defined(__GNUC__)
     #define __attribute__((xxx)) 
 #else
     /*other*/
 #endif

总结

从宏界说下手,了解底层开发原理,能够有助咱们做SDK封装时有更高效的方法,或者供给更简易的运用方法。希望这篇文章对我们有帮助,如有过错望指正。

相关参阅链接:

gcc.gnu.org/onlinedocs/…

www.unixwiz.net/techtips/gn…