只说重点

找到类得信息,如下:

struct _class_t {struct _class_t *isa;struct _class_t *superclass;void *cache;void *vtable;struct _class_ro_t *ro;
};struct _class_ro_t {unsigned int flags;unsigned int instanceStart;unsigned int instanceSize;const unsigned char *ivarLayout;const char *name;const struct _method_list_t *baseMethods;const struct _objc_protocol_list *baseProtocols;const struct _ivar_list_t *ivars;const unsigned char *weakIvarLayout;const struct _prop_list_t *properties;
};

_class_ro_t是类得其他信息,在里面我们可以找到我们平时用到得一些东西,如类名,方法列表、属性列表、继承的协议列表等

ro表示read only的意思, 即只读, 包含名称, 方法, 协议以及实例变量信息, 因为是只读的,所以也就是WWDC说的clean memory,而clean memory在加载到内存后是不会发生改变的。

分类

分类信息如下:

struct _category_t {const char *name;struct _class_t *cls;const struct _method_list_t *instance_methods;const struct _method_list_t *class_methods;const struct _protocol_list_t *protocols;const struct _prop_list_t *properties;
};

上面得分类信息,也就是我们在写分类得时候可以添加什么,实例方法、类方法、协议、属性,成员变量是不能添加得,因为category得底层数据结构根本不支持,当然不排除你用别的方式来实现,实现可以参考这个文章:iOS-Category添加成员变量 Objective-C如何在category里加入成员变量

以下是本人实现得过程,仅做参考:

#import "Person.h"NS_ASSUME_NONNULL_BEGIN@interface Person (Category)@property (nonatomic, copy) NSString *address;
@property (nonatomic, copy) NSString *addressName;
@property (nonatomic, copy) NSString *bigoo;- (void) eat;
@endNS_ASSUME_NONNULL_END#import "Person+Category.h"
#import <objc/runtime.h>static void *strKey = &strKey;
static const char *kFriendsPropertyKey = "kFriendsPropertyKey";
static NSString *addressName_;
//
NSMutableDictionary *bigoos_;@implementation Person (Category)+ (void)load {bigoos_ = [NSMutableDictionary dictionary];
}- (void)eat {NSLog(@"I eat");
}//
- (NSString *)address {return objc_getAssociatedObject(self, kFriendsPropertyKey);
}- (void)setAddress:(NSString *)address {objc_setAssociatedObject(self, kFriendsPropertyKey, address, OBJC_ASSOCIATION_COPY_NONATOMIC);
}//
- (void)setAddressName:(NSString *)addressName {addressName_ = addressName;
}- (NSString *) addressName {return addressName_;
}//
- (void)setBigoo:(NSString *)bigoo {bigoos_[[NSString stringWithFormat:@"%p", self]] = bigoo;
}-(NSString *)bigoo {return bigoos_[[NSString stringWithFormat:@"%p", self]];
}
@end

上面几种方法可以试试。

通过这两个地方我们再来理理objc源码里面是怎么写得,参考如下:

struct objc_class {Class _Nonnull isa  OBJC_ISA_AVAILABILITY;#if !__OBJC2__Class _Nullable super_class                              OBJC2_UNAVAILABLE;const char * _Nonnull name                               OBJC2_UNAVAILABLE;long version                                             OBJC2_UNAVAILABLE;long info                                                OBJC2_UNAVAILABLE;long instance_size                                       OBJC2_UNAVAILABLE;struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif} OBJC2_UNAVAILABLE;

上面得#if !__OBJC2__告诉我们是objc2的话,我们不能用???

好吧,我找到得是以下内容:

struct objc_class : objc_object {// Class ISA;Class superclass;cache_t cache;             // formerly cache pointer and vtableclass_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flagsclass_rw_t *data() { return bits.data();}void setData(class_rw_t *newData) {bits.setData(newData);}void setInfo(uint32_t set) {assert(isFuture()  ||  isRealized());data()->setFlags(set);}void clearInfo(uint32_t clear) {assert(isFuture()  ||  isRealized());data()->clearFlags(clear);}// set and clear must not overlapvoid changeInfo(uint32_t set, uint32_t clear) {assert(isFuture()  ||  isRealized());assert((set & clear) == 0);data()->changeFlags(set, clear);}bool hasCustomRR() {return ! bits.hasDefaultRR();}void setHasDefaultRR() {assert(isInitializing());bits.setHasDefaultRR();}void setHasCustomRR(bool inherited = false);void printCustomRR(bool inherited);bool hasCustomAWZ() {return ! bits.hasDefaultAWZ();}void setHasDefaultAWZ() {assert(isInitializing());bits.setHasDefaultAWZ();}void setHasCustomAWZ(bool inherited = false);void printCustomAWZ(bool inherited);bool instancesRequireRawIsa() {return bits.instancesRequireRawIsa();}void setInstancesRequireRawIsa(bool inherited = false);void printInstancesRequireRawIsa(bool inherited);bool canAllocNonpointer() {assert(!isFuture());return !instancesRequireRawIsa();}bool canAllocFast() {assert(!isFuture());return bits.canAllocFast();}bool hasCxxCtor() {// addSubclass() propagates this flag from the superclass.assert(isRealized());return bits.hasCxxCtor();}void setHasCxxCtor() { bits.setHasCxxCtor();}bool hasCxxDtor() {// addSubclass() propagates this flag from the superclass.assert(isRealized());return bits.hasCxxDtor();}void setHasCxxDtor() { bits.setHasCxxDtor();}bool isSwiftStable() {return bits.isSwiftStable();}bool isSwiftLegacy() {return bits.isSwiftLegacy();}bool isAnySwift() {return bits.isAnySwift();}// Return YES if the class's ivars are managed by ARC, // or the class is MRC but has ARC-style weak ivars.bool hasAutomaticIvars() {return data()->ro->flags & (RO_IS_ARC | RO_HAS_WEAK_WITHOUT_ARC);}// Return YES if the class's ivars are managed by ARC.bool isARC() {return data()->ro->flags & RO_IS_ARC;}#if SUPPORT_NONPOINTER_ISA// Tracked in non-pointer isas; not tracked otherwise
#elsebool instancesHaveAssociatedObjects() {// this may be an unrealized future class in the CF-bridged caseassert(isFuture()  ||  isRealized());return data()->flags & RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS;}void setInstancesHaveAssociatedObjects() {// this may be an unrealized future class in the CF-bridged caseassert(isFuture()  ||  isRealized());setInfo(RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS);}
#endifbool shouldGrowCache() {return true;}void setShouldGrowCache(bool) {// fixme good or bad for memory use?}bool isInitializing() {return getMeta()->data()->flags & RW_INITIALIZING;}void setInitializing() {assert(!isMetaClass());ISA()->setInfo(RW_INITIALIZING);}bool isInitialized() {return getMeta()->data()->flags & RW_INITIALIZED;}void setInitialized();bool isLoadable() {assert(isRealized());return true;  // any class registered for +load is definitely loadable}IMP getLoadMethod();// Locking: To prevent concurrent realization, hold runtimeLock.bool isRealized() {return data()->flags & RW_REALIZED;}// Returns true if this is an unrealized future class.// Locking: To prevent concurrent realization, hold runtimeLock.bool isFuture() { return data()->flags & RW_FUTURE;}bool isMetaClass() {assert(this);assert(isRealized());return data()->ro->flags & RO_META;}// NOT identical to this->ISA when this is a metaclassClass getMeta() {if (isMetaClass()) return (Class)this;else return this->ISA();}bool isRootClass() {return superclass == nil;}bool isRootMetaclass() {return ISA() == (Class)this;}const char *mangledName() { // fixme can't assert locks hereassert(this);if (isRealized()  ||  isFuture()) {return data()->ro->name;} else {return ((const class_ro_t *)data())->name;}}const char *demangledName(bool realize = false);const char *nameForLogging();// May be unaligned depending on class's ivars.uint32_t unalignedInstanceStart() {assert(isRealized());return data()->ro->instanceStart;}// Class's instance start rounded up to a pointer-size boundary.// This is used for ARC layout bitmaps.uint32_t alignedInstanceStart() {return word_align(unalignedInstanceStart());}// May be unaligned depending on class's ivars.uint32_t unalignedInstanceSize() {assert(isRealized());return data()->ro->instanceSize;}// Class's ivar size rounded up to a pointer-size boundary.uint32_t alignedInstanceSize() {return word_align(unalignedInstanceSize());}size_t instanceSize(size_t extraBytes) {size_t size = alignedInstanceSize() + extraBytes;// CF requires all objects be at least 16 bytes.if (size < 16) size = 16;return size;}void setInstanceSize(uint32_t newSize) {assert(isRealized());if (newSize != data()->ro->instanceSize) {assert(data()->flags & RW_COPIED_RO);*const_cast<uint32_t *>(&data()->ro->instanceSize) = newSize;}bits.setFastInstanceSize(newSize);}void chooseClassArrayIndex();void setClassArrayIndex(unsigned Idx) {bits.setClassArrayIndex(Idx);}unsigned classArrayIndex() {return bits.classArrayIndex();}};

不能向编译后得到的类中增加实例变量:因为编译后的类已经注册在 runtime 中,类结构体中的 objc_ivar_list 实例变量的链表和 instance_size 实例变量的内存大小已经确定,同时runtime会调用 class_setvarlayout 或 class_setWeaklvarLayout 来处理strong weak 引用.所以不能向存在的类中添加实例变量,可以看看文章开头编译成C++ 得到得类的实际情况。

能向运行时创建的类中添加实例变量:运行时创建的类是可以添加实例变量,调用class_addIvar函数. 但是的在调用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上

通过将OC编译成C++ 一探究竟(边学编写,帮忙点评)相关推荐

  1. iOS架构-c++工程在Mac下编译成.a库并调用(12)

    请先了解:xcode生成静态库文件.a 前言: 有时侯需要使用c++的一些代码库,这里先讲一下用Xcode 建C++ 工程,并将代码编译成.a库,提供给demo使用.这里只是简单的介绍,以后会继续介绍 ...

  2. 【CLR的执行模型:将源代码编译成托管模块】

    CLR:由多种不同编程语言使用的运行库 托管模块:中间语言和元数据 非托管语言:C/C++,不过此为特殊,可以写成托管代码 托管语言:C# 托管模块 1,PE32/PE32+头:PE32运行在win3 ...

  3. 怎样创造计算机语言,如何创建编译成JavaScript的编程语言

    你曾经想过创建自己的编程语言吗?在本文中,我将演示如何使用免费工具和PEG.js解析器生成器快速编写编译为JavaScript的简单语言. 什么是解析器生成器 解析器生成器顾名思义就是一个基于语法.语 ...

  4. class反编译成java_省事情的java(3)-编译

    摘要 jvm是为了支持java语言的.jvm的具体实现就是运行时环境.那么java语言的源代码怎么变成jvm认可的指令呢?-----这就需要编译器编译. jvm代码 java源程序(.java)是通过 ...

  5. 使用clang将C/C++代码编译成LLVM的中间代码(LLVM ir bitcode),并反汇编LLVM bitcode

    test.c文件内容如下: #include<stdio.h> int main(void){printf("hello world!\n");return 0; } ...

  6. python编译成exe速度会变快吗_python如何编译成exe

    Python 程序都是脚本的方式,一般是在解析器里运行,如果要发布出去,需要提前安装解析器才可以运行,为了在 Windows 里方便发布,只要点击一个 EXE 文件运行,并且打包所需要库文件,这样发布 ...

  7. 通过maven命令将源代码编译成jar到本地仓库

    图: 4.2.3        采用maven命令编译成jar安装到本地maven库 在路径框输入cmd,执行命令: mvn clean install 图: 图2 成功后可以看到jar包 转载于:h ...

  8. aspx-cs-dll :在部署后就让所有的aspx处于已经编译成dll的状态

    aspx->cs->dll asp.net项目在部署后,aspx文件并没有被编译,这种情形要一直维持到用户第一次访问页面,该页面文件aspx才会转化成cs,并编译成dll,这次访问速度不会 ...

  9. python运行过程中会被编译成二进制_Python代码在运行过程中,会被编译成二进制代码。_学小易找答案...

    [单选题]1. ( )是违反设备安全操作规程的错误做法. [单选题]Thank you for your letter ___________ 24th March. (1.0分) [单选题]超外差接 ...

  10. VScode中html怎么引入js,vscode中如何使用typescript,如何自动编译成js文件

    使用vscode创建一个typescript程序 1:介绍 typescript是一个跨平台的编程语言,专门用于前端的语言,是由微软开发,在2013年6月正式发布,它是javascript的超集,扩展 ...

最新文章

  1. oracle瘦连接,java-无法使用jdbc瘦驱动程序连接到oracle数据...
  2. 用 Go 语言实现 Raft 选主
  3. BCB中的RTTI机制
  4. html css加载不了_CSS加载会阻塞页面显示?
  5. 听力阈值计算_中耳功能分析:临床听力测试的重要手段!
  6. Linux学习——echo和read命令用法
  7. android 开发书签大全,一站式的导航分享!
  8. 如果你还不明白Hello,World!
  9. java 包的package和import语句
  10. 零基础学习Java的路线,学完上岸BAT!
  11. java 读写 ini 配置文件【IDEA】
  12. python爬虫-基础入门-python爬虫突破封锁
  13. 自动驾驶|福特将在美国新建自动驾驶汽车工厂 计划未来两年投产
  14. android 地图侧滑栏,Android封装侧滑菜单栏
  15. 分频电路设计(笔记)
  16. 机器学习之数据挖掘算法(一)OneR算法
  17. vbs恶意脚本_vbs恶意软件删除程序的分析
  18. 计算锋生的函数 frontogenesis
  19. MySQL用户IP授权
  20. 屏幕刷新机制小结(九)

热门文章

  1. iOS10.3正式版发布:iOS10.3新功能有哪些? 韩俊强的博客
  2. python word 表格宽度_RPA手把手——python-docx 设置 word 文档中表格格式
  3. 从软件测试培训班出来后找工作的这段经历,教会了我这五件事...
  4. git rebase origin/develop
  5. 软件测试的艺术-读书笔记-0
  6. 【18】微信小程序:05-WePY简介、WePY的安装与运行、WePY文件介绍、WePY框架开发规范与使用
  7. 计科实训 餐馆点菜系统
  8. Github开始强制使用PAT(Personal Access Token)了
  9. hadoop框架介绍
  10. selenium+chromedriver自动打开谷歌进行搜索