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"