美文网首页互联网科技程序员
「类与对象」揭秘本质的第一步

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

作者: Jack_lin | 来源:发表于2019-12-23 23:45 被阅读0次
    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底层数据结构是结构体

    今天就到这了。

    相关文章

      网友评论

        本文标题:「类与对象」揭秘本质的第一步

        本文链接:https://www.haomeiwen.com/subject/tvatoctx.html