「类与对象」揭秘本质的第一步

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命令使用掌握上述几种,就足以开发使用,其他用法还有很多就不在这一一介绍了。

最终使用的命令:

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp

项目实践

创建一个实例项目并将项目中的main.m转换成main.cpp文件,具体展示如下:

code.gif

文件目录相关截图如下:

生成后的代码

main.m相关代码:

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相关代码:

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开发的时候,心中总会有一个疑问:

创建的对象都是继承自`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编译后:

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底层数据结构是结构体

今天就到这了。

扫一扫下面的二维码,欢迎关注我的个人微信公众号:猿视角的动态(ID:iOSDevSkills),可在微信公众号进行留言,更多精彩技术文章,期待您的加入!一起讨论,一起成长!一起攻城狮!

公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值