RunTime 之深入理解实例(Instance)、类对象(Class Object)、元类(MetaClass)

在Objective-C 源码中看看实例的定义

#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif

通过代码可以看出id 是指向struct objc_object结构体的指针,struct objc_object结构体中只有一个成员变量Class类型isa,Class 是指向struct objc_class结构体的指针, 下面看看NSObject 的定义

@interface NSObject  {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
    Class isa  OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}

通过代码可以看出NSObject也只有一个成员变量Class类型isa

id tempStr = [[NSString alloc] init];
NSString *tmpOneStr = [[NSString alloc] init];

以上两种方法都可以表示实例对象
下面看看struct objc_class结构体在runtime.h中

#if !OBJC_TYPES_DEFINED

/// An opaque type that represents a method in a class definition.
/** 方法别名 */
typedef struct objc_method *Method;

/// An opaque type that represents an instance variable.
/** 变量别名 */
typedef struct objc_ivar *Ivar;

/// An opaque type that represents a category.
/** 类别别名 */
typedef struct objc_category *Category;

/// An opaque type that represents an Objective-C declared property.
/** 属性别名 */
typedef struct objc_property *objc_property_t;

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;     // 类的版本信息,默认为0
    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;
/* Use `Class` instead of `struct objc_class *` */

#endif

OC 中的类也是一个对象,称为类对象,类对象就是一个结构体struct objc_class,这个结构体存放的数据称为元数据(metadata),类对象在编译期用于创建实例对象,是单例。
看一下NSObject.mm中的代码

+ (Class)class {
    return self;
}

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

上面的类方法+ (Class)class和实例方法- (Class)class返回的都是类对象。
先看一下object_getClass方法

/** 
 * Returns the class of an object.
 * 
 * @param obj The object you want to inspect.
 * 
 * @return The class object of which \e object is an instance, 
 *  or \c Nil if \e object is \c nil.
 */
OBJC_EXPORT Class _Nullable
object_getClass(id _Nullable obj) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

object_getClass 用于获取对象的isa指针指向的对象
验证类方法+ (Class)class和实例方法- (Class)class返回的都是类对象:

    DMFunctionClassModel *tempModel = [[DMFunctionClassModel alloc] init];
    if ([DMFunctionClassModel class] == [tempModel class]) {
       NSLog(@"[DMFunctionClassModel class] 和 [tempModel class] 获取的是类对象");
    }

输出如下


1.png

类对象的isa指针指向的我们称之为元类(metaClass),元类中保存了创建类对象以及类方法所需的所有信息

/** 
 * Returns a Boolean value that indicates whether a class object is a metaclass.
 * 
 * @param cls A class object.
 * 
 * @return \c YES if \e cls is a metaclass, \c NO if \e cls is a non-meta class, 
 *  \c NO if \e cls is \c Nil.
 */
OBJC_EXPORT BOOL
class_isMetaClass(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

class_isMetaClass 用于判断Class 对象是否为元类

 BOOL isMeta = class_isMetaClass(object_getClass([DMFunctionClassModel class]));
    if (isMeta) {
        NSLog(@"object_getClass([DMFunctionClassModel class]) 获取的是元类");
    }

输出如下:


2.png

通过输出可以知道类对象的isa指针指向的是元类
下图清晰的展示了实例、类对象、元类之间的关系


3.png

下面区分一下

- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
+ (BOOL)isSubclassOfClass:(Class)aClass;

这三个函数,可以看一下源码实现NSObject.mm中

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

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

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

可以知道,isMemberOfClass只是判断类对象和传入的Class对象是否相同,isKindOfClass和isSubclassOfClass都会按照继承关系一层一层和传入的Class对象比较,直到nil为止。isKindOfClass和isSubclassOfClass的不同是一个是实例方法一个是类方法。

你可能感兴趣的:(RunTime 之深入理解实例(Instance)、类对象(Class Object)、元类(MetaClass))