Clang 命令
1、将.m文件转成.cpp,由oc转成c++,方便查看大概的源码实现。
clang -rewrite-objc xxx.m (xxx指文件名)
如果报错,例如 fatal error: 'UIKit/UIKit.h' file not found,可用以下命令代替
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk xxx.m
Clang Attributes
2、objc_subclassing_restricted
定义不可继承的类
__attribute__((objc_subclassing_restricted))
@interface MyCar : NSObject
@end
3、objc_requires_super
子类继承父类方法时,必须调用super,否则产生警告。
@interface Father : NSObject
- (void)playGame __attribute__((objc_requires_super));
@end
@implementation Father
- (void)playGame {
NSLog(@"play cs");
}
@end
@interface Son : Father
@end
@implementation Son
- (void)playGame {
} //warning missing [super playGame]
@end
4、objc_boxable
可用语法糖将struct或者union类型装箱成NSValue对象
typedef struct __attribute__((objc_boxable)) {
CGFloat x, y, width, height;
} XXRect;
XXRect rect = {1, 2, 3, 4};
NSValue *value = @(rect);
5、constructor / destructor
构造器和析构器,分别在可执行文件load和unload时被调用,constructor比load晚,比main函数早。
可有多个constructor, attribute((constructor(101))),数字越小优先级越高,1 ~ 100 为系统保留。
__attribute__((constructor))
static void beforeMain(void) {
NSLog(@"beforeMain");
}
__attribute__((destructor))
static void afterMain(void) {
NSLog(@"afterMain");
}
int main(int argc, const char * argv[]) {
NSLog(@"main");
return 0;
}
// 输出: beforeMain -> main -> afterMain
6、enable_if
只能用在 C 函数上,可以用来实现参数的静态检查:
static void test(int a)
__attribute__((enable_if(a > 0 && a < 10, "不在此范围内"))) {
printf("%d", a);
}
7、cleanup
用来声明变量,当此变量作用域结束时,调用指定的C方法。
static void callback(__strong NSString **string) {
NSLog(@"%@", *string);
}
{
//该变量作用域,作用域结束时调用callback
__strong NSString *string __attribute__((cleanup(callback))) = @"abc";
}
执行输出: abc
8、overloadable
用于 C 函数,可以定义若干个函数名相同,但参数不同的方法,调用时编译器会自动根据参数选择函数原型:
__attribute__((overloadable)) void testMan(int number) {
NSLog(@"%@", @(number));
}
__attribute__((overloadable)) void testMan(id obj) {
NSLog(@"%@", obj);
}
__attribute__((overloadable)) void testMan(CGRect rect) {
NSLog(@"%@", NSStringFromCGRect(rect));
}
testMan(@"123");
testMan(234);
testMan(CGRectMake(1, 2, 3, 4));
9、objc_runtime_name
将类或协议的名字在编译时指定成另一个,常用在代码混淆。
__attribute__((objc_runtime_name("MyCar")))
@interface MyBike : NSObject
@end
NSLog(@"%@", NSStringFromClass([MyBike class])); // "MyCar"