注册

探究iOS鲜为人知的小秘密一一__attribute__运用

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关键词

cdf9cf0732b7a2ae7d2ae48d9e6efa93.png

※objc_requires_super

使用这个属性标志子类继承这个方法时需要调用super,否则给出编译警告,来让父类中有一些关键代码是在被继承重写后必须执行

#define NS_REQUIRES_SUPER __attribute__((objc_requires_super))

c44427b4fb48d7ad34adb0e25ab3c0e2.png

在Switf中也还是可以用final的方法来达到这个目的

c363412d2c164f449f9e5d50ae6ab5da.png

Swift equivalent to __attribute((objc_requires_super))?(stackoverflow)

关于Swift中的final的详细讲解

※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(...))),用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法,个人感觉这个真的很方便

cce9ed3896abb0a244d3462ca2ee9dd2.png

一个对象可以这样用,那么block实际也是一个对象,这样就可以写一个宏,实际上就是ReactiveCocoa中神奇的@onExit

#define onExit\

__strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

有时候我们需要用到锁这个东西,或者一些CoreFoundation的对象有时候最后需要释放,用这个宏就很方便了

d5b4c876bac1e02c272b974207062a8c.png

为了好看用这个宏的时候加个@就加个释放池就可以了

613395351bc54d74a8ecd8acf2e79495.png

sunnyxx这篇博客讲的很清楚

Swift中:可以用defer

9ee4a4ec188134a82341c24925729bff.png

还有一些format, const, noreturn, aligned , packed, objc_boxable, constructor / destructor, enable_if, objc_runtime_name可以看这两篇文章:

神奇的attribute

Clang Attributes黑魔法小记

链接:https://www.jianshu.com/p/33d7d0596028

0 个评论

要回复文章请先登录注册