iOS 面试总结- 类的本质(一)

作者 : 开心源码 本文共2002个字,预计阅读时间需要6分钟 发布时间: 2022-05-12 共295人阅读

类的分类:

实例对象(instance)
类对象(class)
元类对象(meta-class)

问题:

1.类信息是存放在什么地方的呢?

实例对象:存放的具体对象的成员变量的值,
类对象中存放着:类的属性,成员变量,对象方法信息,协议信息,isa,superclass
元类对象中存放着:类方法信息,isa,superclass
每个类在内存中有且只有一个class对象(类对象),有且只有一个元类对象

[NSObject class]  //类对象的获取Class meteClass = object_getClass([NSObject class]); //元类对象获取

2.一个NSObject对象占用多少内存?

在系统alloc的时候,会分配16个字节。(通过malloc_size函数验证)
但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数验证)
当小于16个字节时,系统也会默认开拓16个字节的空间用于存放对象。

3.每个对象中都有一个isa指针。这个指针的作用是什么呢?

instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象
NSObject的元类isa指向自身、superclass指向NSObject的类对象。这样才能形成一个闭环。
文字太枯燥,show me the code

@interface JQApple : JQFruit@end@implementation JQApple- (instancetype)init{    self = [super init];    if (self) {        NSLog(@"%@", NSStringFromClass([self class]));        NSLog(@"%@", NSStringFromClass([super class]));    }    return self;}@end

转自https://www.songma.com/p/b1274e3e3768,里面有详解。

4.如何查看Class能否为meta-class
BOOL result  = class_isMetaClass([NSObject class]);

看到这里,我们大概已经理解了对象接收到消息时,oc中消息分发机制。

5.那么有个疑问哈,既然对象的消息响应要走这么长一段流程,那么对象响应性能岂不是很慢吗?但实际上oc中的响应效率是很高的。系统这里面是做的什么操作呢?

苹果底层用散列表缓存了方法,缓存过程中会通过方法名作为key,用指针地址&上一个mask(mask的值为散列表长度-1,这样保证了得出的索引值小于散列表的长度),从而求出索引值,根据索引值来存放方法实现。当想对象放松objc_send的时候,也是通过该方法获取索引值。这样通过一个位运算即可以取得方法的实现。

附:
消息分发机制过程:

1.在Objective-C中,方法调用是一个消息发送的过程(在java,C++等静态语言中是函数调用)。OC对象发送一个消息的过程如下:1.向对象发送消息2.在缓存中查找能否有匹配方法。假如有则响应,否则继续3.在对象的类对象的方法列表中(method list)查找能否有匹配方法,假如有则响应,否则继续4.在对象的父类的缓存中查找能否有匹配方法。假如有则响应,否则继续5.在对象的父类的方法列表中(method list)查找能否有匹配方法。假如有则响应,否则继续6.进入动态解析 -(BOOL)resolveInstanceMethod:(SEL)sel;- (BOOL)resolveClassMethod:(SEL)sel;查看能否有动态增加方法实现。假如有则响应,否则继续7.进入消息重定向 -(id)forwardingTargetForSelector:(SEL)sel;假如有指定消息接收对象则响应,否则(指:返回nil或者者self)继续8.进入方法签名- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector返回方法签名并进入下一步,否则调用doesNotRecongnizeSelector:方法并抛出异常。9.进入消息转发 - (void)forwardInvocation:(NSInvocation *)aInvocation;假如有指定消息转发对象则响应,否则调用doesNotRecongnizeSelector:方法并抛出异常。

我们思考个问题:

有person类和student类class Person{    +(void)test{        nslog(@"123");    }}class Student : Person{}当用一个Student对象调用test方法时,打印会执行么?[[Student alloc] test];

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS 面试总结- 类的本质(一)

发表回复