0-1-0-1
Objective-C本身是一种高级语言,底层都是由C/C 实现。
若想了解Objective-C一些API具体实现以及一些对象真实的数据结构等,就需要将Objective-C语言转化成C/C 语言。
OC代码的转换过程
OC语言转化成C/C 的相关命令
- 需要使用的命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
- 使用Xcode自带的命令:
xcrun
- 选择指定编译平台(SDK):
iphoneos
,查看所有的支持的SDK,执行命令xcodebuild -sdks
,结果如下:
查看支持的SDK
- 选择指定架构,可以选择模拟器(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
命令使用掌握上述几种,就足以开发使用,其他用法还有很多就不在这一一介绍了。
最终使用的命令:
代码语言:javascript复制xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
项目实践
创建一个实例项目并将项目中的main.m转换成main.cpp文件,具体展示如下:
code.gif
文件目录相关截图如下:
生成后的代码
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复制struct 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开发的时候,心中总会有一个疑问:
代码语言:javascript复制创建的对象都是继承自`NSObject`类,那`NSObject`类底层数据结构是什么呢?
今天,就用上面的编译命令,一探NSObject
类真实面目!
1、在main.m文件中创建一个新的NSObject对象:
代码语言:javascript复制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语言中的声明:
@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
结构相似的结构,如下所示:
struct NSObject_IMPL {
Class isa;
};
IMPL
一般是Implementation
缩写,从而从侧面验证了NSObject
底层数据结构是结构体。
今天就到这了。