NSObject对象模型解析(下)

作者: 北辰明 | 来源:发表于2016-06-25 15:33 被阅读228次

原创文章转载请注明出处,谢谢


这一节的主要内容是解析NSObject的一些类方法和实例方法,我会挑几个比较常用的方法入手来讲。我们知道NSObject实现了NSObject协议,所以NSObject协议里所有的@required的声明,在NSObject的源码里都是有实现的。类对象在OC中是一个单例的对象,所以类对象的内存地址是不会变的,基本上所有的实例方法都会有一个对应的类方法,只是有些类方法并没有被Public出来,所以我们没有感觉到。

接下来我们就开始具体用一些常用的方法来看看它们的具体实现。

self

+ (id)self {
    return (id)self;
}

- (id)self {
    return self;
}

上面这两个方法是平时使用频率非常高的方法了,那么它们到底是什么意思呢?对于一个类对象来讲self返回的其实是一个指向objc_class对象的指针的地址;对于一个实例对象来讲self返回的其实是一个指向objc_object对象的指针地址,这弄清楚这点对于后面所有方法的理解会很有帮助。

Class

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

// Unit Test
BClass *clazz = [[BClass alloc] init];
NSLog(@"%p", clazz);
NSLog(@"%p", [BClass class]);
NSLog(@"%p", [clazz class]);

// Output
2016-06-25 14:33:55.405 InitDemo[8037:116623] 0x100105de0
2016-06-25 14:33:55.406 InitDemo[8037:116623] 0x100002788
2016-06-25 14:33:55.406 InitDemo[8037:116623] 0x100002788

上面这两个方法其实是返回一个指向objc_class的对象指针,从上面的单元测试可以看出它们两个返回的地址是一样的,因为实例对象的class方法其实是调用了object_getClass方法,返回的是isa指针指向的地址也就是BClass的类对象(也就是objc_object的isa指针),而BClass的类方法class返回的其实就是它自己,所以两个地址是相等的(参考上一节的图就可以明白了)。而单单clazz的objc_object首地址是和它们不相同的。

superclass

+ (Class)superclass {
    return self->superclass;
}

- (Class)superclass {
    return [self class]->superclass;
}

// Unit Test
BClass *clazz = [[BClass alloc] init];
NSLog(@"%p", [BClass superclass]);
NSLog(@"%p", [AClass class]);
NSLog(@"%p", [clazz superclass]);

// Output
2016-06-25 14:46:59.070 InitDemo[8108:121893] 0x100002748
2016-06-25 14:46:59.071 InitDemo[8108:121893] 0x100002748
2016-06-25 14:46:59.071 InitDemo[8108:121893] 0x100002748

这两个方法其实很容易理解,就是返回对象的superclass,无论是类对象还是实例对象,它们的superclass都是同一个对象。

isMemberOfClass

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

// Unit Test
BClass *clazz = [[BClass alloc] init];
NSLog(@"%@", [clazz isMemberOfClass:[BClass class]]? @"YES" : @"NO");
NSLog(@"%@", [BClass isMemberOfClass:object_getClass([BClass class])]? @"YES" : @"NO");

// Output
2016-06-25 15:07:25.487 InitDemo[8187:129155] YES
2016-06-25 15:07:25.488 InitDemo[8187:129155] YES

这个方法Public出来的只有实例方法,类方法是没有的。因为实例方法其实就是判断某个实例对象是否是某个类的实例,而类方法判断的其实是某个类对象是否是某个metaclass的类对象,因为其实正常是没有必要需要这个类方法去判断metaclass的,所以才没有public出来这个方法,这是我猜测的原因,大家可以看看单元测试很容易理解,当然这里需要自己定义一个isMemberOfClass类方法。

isKindOfClass

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

判断是否是这个类或者这个类的子类的实例
isKindOfClass也和isMemberOfClass一样,只public出来的实例方法,没有类方法,因为实例方法是去判断某个实例对象是否是某个类或者其子类的实例,而类方法就是去判断某个类对象是否是某个metaclass或者其子类的类对象,看起来很绕,其实很容易理解的。

isSubclassOfClass

+ (BOOL)isSubclassOfClass:(Class)cls {
    for (Class tcls = self; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

// Unit Test
NSLog(@"%@", [BClass isSubclassOfClass:[AClass class]]? @"YES" : @"NO");
NSLog(@"%@", [AClass isSubclassOfClass:[AClass class]]? @"YES" : @"NO");

// Output
2016-06-25 15:23:33.464 InitDemo[8258:135774] YES
2016-06-25 15:23:33.465 InitDemo[8258:135774] YES

这个方法是没有实例方法的,因为没有这个必要,它的作用就是判断某个类对象是否是某个类对象的子类或者本身,对于实例对象可以用isKindOfClass来完成。

总结

其实讲解析方法的部分主要目的是对前面的认知做一个深入的理解,所以我并有讲NSObject里其他的那些方法,只讲了这些和前面概念有关联的这部分,主要目的就是加深理解

相关文章

  • NSObject对象模型解析(下)

    原创文章转载请注明出处,谢谢 这一节的主要内容是解析NSObject的一些类方法和实例方法,我会挑几个比较常用的方...

  • NSObject对象模型解析(上)

    原创文章转载请注明出处,谢谢 很早就想讲关于NSObject这个对象的模型,其实网上有不少讲这方面知识的,但是我感...

  • IOS基础:NSObject对象模型解析

    原创:知识点总结性文章创作不易,请珍惜,之后会持续更新,不断完善个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈...

  • 一个NSObject对象占用多少内存

    问题提出: 解析过程 要知道NSObject对象占用多少内存,需要知道创建一个NSObject对象的时候都做了什么...

  • Objective C的对象模型

    Objective C的对象模型 绝大多数对象继承自NSObject,NSObject就是一个包含isa指针的结构...

  • IOS JSON数据解析

    解析成对象放到数组中 Author 对象头文件 @interface Author : NSObject@prop...

  • JavaScript 重点

    JSHTML DOM JS浏览器BOM 文档对象模型,浏览器对象模型 通过元素标签解析,通过元素对象进行解析 ==...

  • 模型

    模型 - 什么是模型? - 专门用来存放数据的对象 - 一般都是一些直接继承自NSObject的纯对象...

  • 解析XML

    解析方式 DOM MAC提供的解析方法 (Document Object Model ,文档对象模型。解析时需要...

  • 2018-07-03

    NSObject的内存本质 1.实例化一个NSObject对象 (arm64位系统情况下) NSObject *o...

网友评论

    本文标题:NSObject对象模型解析(下)

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