Cocoa中常用的宏定义

独奏

技术分享|2016-3-4|最后更新: 2023-2-23|
type
status
date
slug
summary
tags
category
icon
password
我们在 Cocoa 的头文件中常会看到很多宏定义,这里列举几个可能会用到的

NS_AVAILABLE

这个宏定义常用于 API 版本控制,表明函数/属性的使用版本,是否废弃等情况,用法如下:
该方法在 iOS 4.0 中引入
该方法在 OS X 10.6 和 iOS 4.0 中引入
该方法在 iOS 2.0 中引入在 iOS 6.0 后废弃
该方法在 OS X 10.0 以及 iOS 2.0 引入,在 OS X 10.6 以及 iOS 4.0 后废弃

NS_ASSUME_NONNULL

这个属性是 objective-c 3.0中引入的新功能,应该是为了和 swift 做兼容的。因为 swift 是有严格的类型检查的,而在objc一向是动态性很强的语言,所以为了和 swift 做兼容,也引入了一些类型检查相关的属性,这就是其中一个
使用这个宏把整个类包起来,表明类中所有指针类型都不能显示地置为 nil。
比如
可见,NS_ASSUME_NONNULL_BEGIN 只对 显式赋值nil 这种情况编译器会给出警告,所以为了安全起见,代码中依然要对 nil 进行安全判断。
我们通常把这个宏和 nullable 一起使用,比如 AFNetworking 里面的用法

深入挖掘

我们深入AVAILABLE相关宏内部,发现其使用了 __attribute__ 这个编译命令,先看 NS_AVAILABLE 的相关定义
在 iOS 平台上,CF_AVAILABLE 是这样定义的:
下面展开一个方法
展开后

__attribute__

关键字 __attribute__ 是一个编译命令,它可以在变量、函数、类型定义时提供一些「属性」,用来增加一些特殊的用法。这篇文章着重介绍下函数属性和变量属性。

函数属性

availability

availability 遍布于众多的 Cocoa 头文件中,提供对「方法调用」的「控制力度」。
上面已写过这里不再赘述。

objc_requires_super (OC 方法)

父类方法声明时,加上:
表示子类重写该方法时,一定要调用 super 函数,否则 xCode 给出警告。

枚举中的 attribute

枚举中可能有些过时的,可以加上 deprecated 来注明,如果用户使用该值,xCode 会给出warning。

sentinel (OC 方法、C 函数)

明确变参函数需要 nil 参数作为分界
输入代码会自动在后面补一个 nil:
notion image

warn_unused_result (OC 方法、C 函数)

表示用户一定要使用函数的返回值,否则给出 warning。
比如定义一个函数,并用 warn_unused_result 修饰:
如果这样调用,xCode 会给出警告:
提示你,此函数的返回值很重要,你应该加以关注:

nonnull (OC 方法、C 函数)

这个上面同样说过,不再赘述

变量属性

cleanup

表示在变量作用域即将结束时,自动执行一个指定的方法。
举个例子:
当然,除了纯量类型,cleanup 也可以修饰 OC 对象:
如果修饰 block:
上述代码直接在 blockCleanUp函数里调用这个block,也就是说,某些我们想做的事情,可以不必依赖于 cleanup 函数,而在 block 里面直接写出来就好。比如某些成对的操作:
可以考虑写成:
像这样子把成对的操作用这种方式写在一起,防止遗忘,把具体操作移到下方。使用时要一定注意自己的业务场景以及变量的作用域。

objc_runtime_name

修改类在 runtime 中的名称
之后 Father 类在 runtime 中真实名称就变成了 NewFather,通过:
Class class1 = NSClassFromString(@“Father”); 是获取不到类的,必须要通过:
Class class1 = NSClassFromString(@“NewFather”); 才可以。
而且通过:Father *fa = [[Father alloc] init]; 创建一个实例,实例的 isa 为 NewFather。

unused

明确变量即使不使用,也不会产生 warning。平时如果这么定义:
xCode会产生警告,因为 i 以后没有使用过。
这么写可以去除这个警告:

deprecated

表示变量已经不建议使用。
访问 str 时会给出警告。

__attribute__ 到底对谁有用

__attribute__ 是在编译阶段起作用的,给函数、变量提供了更多的错误检查、版本控制等能力。其实平时代码中用的并不多,但是如果你在项目中负责公共组件的维护,有些还是很有用的,比如,当接口更新时,用 availability 去标明接口的使用版本、是否废弃;用 objc_requires_super 来要求子类需要调用父类方法等等。

参考