Clang Attributes是Clang提供的一种源码注解,方便开发者向编译器表达某种要求,参与控制如Static Analyzer、Name Mangling、Code Generation等过程,一般以attribute(xxx)的形式出现在代码中;为方便使用,一些常用属性也被Cocoa定义成宏,比如在系统头文件中经常出现的NS_CLASS_AVAILABLE_IOS(9_0)就是attribute(availability(...))这个属性的简单写法。
※unavailable
#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
可以加在方法声明的后面,告诉编译器该方法不可用
Swift中
@available(*, unavailable)
func foo() {}
@available(iOS, unavailable, message="you can't call this")
func foo2() {}
※availability
#define NS_DEPRECATED_IOS(_iosIntro,_iosDep,...) CF_DEPRECATED_IOS(_iosIntro,_iosDep,__VA_ARGS__)
展开看
#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...)
__attribute__((availability(ios,introduced=_iosIntro,deprecated=_iosDep,message="" __VA_ARGS__)))
再展开看
__attribute__((availability(ios,introduced=2_0,deprecated=7_0,message=""__VA_ARGS__)))
iOS即是iOS平台
introduced从哪个版本开始使用
deprecated从哪个版本开始弃用
message警告的信息
其实还可以再加一个参数例子:
void f(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
obsoleted完全禁止使用的版本
NS_AVAILABLE_IOS(7_0)
iOS7.0或之后才能使用
NS_DEPRECATED_IOS(2_0,6_0)
iOS2.0开始使用6.0废弃
Swift中:
@available(iOS 6.0, *)
public var minimumScaleFactor: CGFloat
@available(OSX, introduced=10.4, deprecated=10.6, obsoleted=10.10)
@available(iOS, introduced=5.0, deprecated=7.0)
func foo3() {}
※objc_subclassing_restricted
一句话就是使用这个属性可以定义一个不可被继承的类
__attribute__((objc_subclassing_restricted))
@interface Eunuch : NSObject
@end
@interface Child : Eunuch//如果继承它会报错
@end
在Swift中对原来的很多attribute的支持现在还缺失中,为了达到类似的目的,我们可以使用一个final关键词
※objc_requires_super
使用这个属性标志子类继承这个方法时需要调用super,否则给出编译警告,来让父类中有一些关键代码是在被继承重写后必须执行
#define NS_REQUIRES_SUPER __attribute__((objc_requires_super))
在Switf中也还是可以用final的方法来达到这个目的
Swift equivalent to __attribute((objc_requires_super))?(stackoverflow)
※overloadable
用于C函数,可以定义若干个相同函数名,但参数不同的方法,调用时编译器会自动根据参数选择函数去调用
__attribute__((overloadable))
void logAnything(id obj) {
NSLog(@"%@", obj);
}
__attribute__((overloadable)) void logAnything(int number) {
NSLog(@"%@", @(number));
}
__attribute__((overloadable)) void logAnything(CGRect rect) {
NSLog(@"%@", NSStringFromCGRect(rect));
}
// Tests
logAnything(@[@"1", @"2"]);
logAnything(233);
logAnything(CGRectMake(1, 2, 3, 4));
有兴趣的可以写一个自定义的Log免去用NSLog要写@""等格式的麻烦
※cleanup
__attribute__((cleanup(...)))
,用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法,个人感觉这个真的很方便
一个对象可以这样用,那么block实际也是一个对象,这样就可以写一个宏,实际上就是ReactiveCocoa中神奇的@onExit
#define onExit\
__strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^
有时候我们需要用到锁这个东西,或者一些CoreFoundation的对象有时候最后需要释放,用这个宏就很方便了
为了好看用这个宏的时候加个@就加个释放池就可以了
Swift中:可以用defer
还有一些format, const, noreturn, aligned , packed, objc_boxable, constructor / destructor, enable_if, objc_runtime_name
可以看这两篇文章: