Objective-C本身是一种高级语言,底层都是由C/C 实现。
若想了解Objective-C一些API具体实现以及一些对象真实的数据结构等,就需要将Objective-C语言转化成C/C 语言。
OC语言转化成C/C 的相关命令
- 需要使用的命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
- 使用Xcode自带的命令:xcrun;
- 选择指定编译平台(SDK):iphoneos,可通过下面的命令查看所有的支持的SDK,执行命令xcodebuild -sdks,结果如下:
- 选择指定架构,可以选择模拟器(i386)、x86_64、64bit(arm64)、32bit(armv7),由于IPhone属于arm64架构,所以添加参数:-arch arm64
- 默认使用的是Clang编译器:需要使用clang相关命令;
- 若想支持ARC,需要添加-fobjc-arc编译参数;
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc main.m -o main.cpp
- 若想指定运行时的系统版本,可以添加-fobjc-runtime=ios-8.0.0:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m -o main.cpp
- 若需要指定框架:需要添加-framework 参数,比如-framework UIKIt:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m -o main.cpp -framework Foundation
... 还有许多
关于xcrun命令使用掌握上述几种,就足以开发理解和使用了,许多其他用法就不在本文一一介绍了。
最终使用的命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
验证本质
创建一个实例项目并将项目中的main.m转换成main.cpp文件,具体展示如下:
(项目地址:https://github.com/123sunxiaolin/JLPractice/tree/master/JLClassAndObjPractice)
文件目录相关截图:
main.m相关代码:
代码语言:javascript复制int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { // Setup code that might create autoreleased objects goes here. appDelegateClassName = NSStringFromClass([AppDelegate class]); } return UIApplicationMain(argc, argv, nil, appDelegateClassName);}
main.cpp相关代码:
代码语言:javascript复制truct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS;};/* @end */
int main(int argc, char * argv[]) { NSString * appDelegateClassName; /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
appDelegateClassName = NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class"))); } return UIApplicationMain(argc, argv, __null, appDelegateClassName);}static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
我想,大家刚开始做iOS开发的时候,心中总会有一个疑问:
创建的对象都是继承自NSObject类,那NSObject类底层数据结构是什么呢?
今天,就用上面的编译命令,一探NSObject类真实面目!
1、在main.m文件中创建一个新的NSObject对象:
int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { // Setup code that might create autoreleased objects goes here. appDelegateClassName = NSStringFromClass([AppDelegate class]); // 创建一个NSObject对象 NSObject *obj = [[NSObject alloc] init]; } return UIApplicationMain(argc, argv, nil, appDelegateClassName);}
2、clang编译后:
代码语言:javascript复制struct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS;};
int main(int argc, char * argv[]) { NSString * appDelegateClassName; /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
appDelegateClassName = NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")));
NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
} return UIApplicationMain(argc, argv, __null, appDelegateClassName);}
3、查看一下NSObject在Objective-C语言中的声明:
代码语言:javascript复制@interface NSObject <NSObject> {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wobjc-interface-ivars" Class isa OBJC_ISA_AVAILABILITY;#pragma clang diagnostic pop}
精简后:@interface NSObject <NSObject> { Class isa;}
那么它对应的真实数据结构是什么呢?
于是在刚刚编译后的main.cpp文件中,搜索NSObject关键字,经过筛选比对,最后找到一个与上述NSObject结构相似的结构,如下所示:
代码语言:javascript复制struct NSObject_IMPL { Class isa;};
IMPL一般是implementation缩写,从而从侧面验证了NSObject底层数据结构是结构体。
NSObject所对应的的结构体,仅包含一个成员变量isa,isa主要存放Objective-C对象的地址。
今天先到这。