浅谈 __attribute__

__attribute__ 是一个编译器指令,其实是 GNU C 的一种机制,本质是一个编译器的指令,在声明的时候可以提供一些属性,在编译阶段起作用,来做多样化的错误检查和高级优化。用于在 CC++Objective-C 中修饰变量、函数、参数、方法、类等。

合理使用 __attribute__ 有什么好处?

  • 给编译器提供上下文,帮助编译器做优化,合理使用可以收到显著的优化效果。
  • 编译器会根据 __attribute__ 产生一些编译警告,使代码更规范。
  • 给代码阅读者提供必要的注解,助其理解代码意图。

总之,__attribute__ 起到了给编译器提供上下文的作用,如果错误的使用 __attribute__ 指令,因为给编译器提供了错误的上下文,由此引起的错误通常很难被发现。

deprecated

适用于方法、属性。告诉编译器已经过时,如果使用了,会报过时警告

常用写法:

// 可以自定义描述信息
__attribute__((deprecated("已过期!")))
// 系统的宏定义
DEPRECATED_ATTRIBUTE 

使用场景:

在组件化、SDK 的时候,因为某个需求,我们升级了 API,但是需要兼容老的版本,并且希望使用者调用最新的 API

// 标记这个属性已过期
@property (nonatomic, copy) NSString *name __attribute__((deprecated("属性已过期")));

// 标记方法已过期
- (void)testOld __attribute__((deprecated("方法已过期, 请使用 test2"))) {  

}

- (void)testNew {

}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    // 编译器警告,'testOld' is deprecated: 已过期, 请使用 testNew
    [self testOld];

    // 编译器警告,提示 "'name' 已过期..."
    NSLog(@"%@", self.name);
}

unavailable

适用于方法、属性。告诉编译器不可用。如果使用了,就会编译失败,提示错误信息

常用写法:

// 可以自定义描述信息
__attribute__((unavailable("已经废弃,请使用 xxxx")))
// 系统宏定义
NS_UNAVAILABLE;
UNAVAILABLE_ATTRIBUTE;

使用场景:

自定义了 Class 的初始化方法,不希望外界使用 init 初始化,并且给出正确的提示。
比希望继续使用某个属性,并且给出正确的提示。

@interface ViewController : UIViewController

@property (nonatomic, copy) NSString *name __attribute__((unavailable("这个属性已经废弃")));

#pragma mark - 初始化
- (instancetype)init __attribute__((unavailable("这个方法已经废弃,请使用 initWithName:")));

- (instancetype)initWithName:(NSString *)Name;
@end

- (void) test {
    // 编译不通过,提示 "'init' 已经废弃了..."
    ViewController *vc = [[ViewController alloc] init];

    // 编译不通过,提示 "'name' 已经废弃了..."
    NSLog(@"%@", vc.name);
}

objc_subclassing_restricted

适用于 Class。告诉编译器我不能有子类,类似 final 关键字

常用写法:

__attribute__((objc_subclassing_restricted))

使用场景:

#import <Foundation/Foundation.h>

__attribute__((objc_subclassing_restricted))
@interface ClangTest : NSObject
@end

#import "ClangTest.h"

// 这里编译出错,提示“Cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute”
@interface ClangSonTest : ClangTest
@end

objc_requires_super

适用于方法。告诉编译器子类重写这个方法的时候,必须调用[Super xxx]

常用写法:

// 通用写法
__attribute__((objc_requires_super))

// 系统宏定义,其实和上面是一样的
NS_REQUIRES_SUPER

使用场景:

#import <Foundation/Foundation.h>

@interface ClangTest : NSObject

- (void)instanceMethod1 __attribute__((objc_requires_super));
@end


#import "ClangTest.h"

@interface ClangSonTest : KDClangTest
@end
@implementation KDClangSonTest

- (void)instanceMethod1 {
    NSLog(@"I am son");
    // 这里编译器会出现警告: Method possibly missing a [super instanceMethod1] call
}

constructor 与 destructor

使用 constructor 属性修饰的函数能在 main() 函数之前执行,而使用 destructor 属性修饰的函数,在 main() 函数结束或 exit() 函数调用后执行。

// main之前调用
__attribute__((constructor))

使用场景:

__attribute__((constructor)) void before_main() {
    printf("app before main\n");
}

__attribute__((destructor)) void after_main() {
    printf("app after main\n");
}

int main(int argc, char * argv[]) {
    printf("excute main\n");
    return 0;
}

注意:
因为 load 是在 class 被加载的时候,就执行了,所以早于 constructor
所以顺序应该是:

load -> attribute((constructor)) -> main -> attribute((destructor)) -> initialize

参考链接

https://nshipster.cn/attribute/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容