首页 > 代码库 > 深入学习Objective-C的NSObject

深入学习Objective-C的NSObject

先来看看NSObject的主要定义如下所示(包括一些我的理解注释):

@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

/* Initializing a Class */

/**
 *  @author Arbboter, 15-01-15 22:01:47
 *
 *  如果当前类或者分类实现了load方法才会调用该方法,否则调用父类的方法。
 *  是么时候调用该方法:当类或者其分类在静态链接或者动态加载的时候调用该方法
 *  因此,当import类的头文件的时候,会调用load方法
 */
+ (void)load;

/**
 *  @author Arbboter, 15-01-15 22:01:37
 *
 *  在runtime时第一次调用类的方法(实例方法或者类方法,不包括load方法)
 *  前会调用该方法,而且显示调用层次是从父类到子类(这一点和对象的初始化一致)。
 *  如果子类没有实现该方法,会直接调用父类的,需要注意的是,如果有继承层次为:
 *  class_1 <- class_2 <- class_3
 *  而只有class_1实现了该方法,那么创建一个clsaa_3的对象的时候,会调用该方法
 *  三次(每一层类都会调用该方法),且都是class_1实现的方法
 */
+ (void)initialize;

/* Creating, Copying, and Deallocating Objects */

/**
 *  @author Arbboter, 15-01-15 22:01:57
 *  创建一个当前类的实例变量所需的内存
 *  @param zone 已经忽略
 *  @return 分配的对象
 */
+ (instancetype)allocWithZone:(struct _NSZone *)zone;

/**
 *  @author Arbboter, 15-01-15 23:01:06
 *  由于历史问题,该方法会调用allocWithZone方法创建对象内存
 *  @return 分配了内存的对象
 */
+ (instancetype)alloc;

/**
 *  初始化对象的isa为描述类的数据结构,其他的实例变量为0
 */
- (instancetype)init;

/**
 *  @author Arbboter, 15-01-15 23:01:57
 *  相当于 [[类名 alloc] init]
 *  @return 初始化好的对象
 */
+ (instancetype)new;

/**
 *  @author Arbboter, 15-01-15 23:01:49
 *  由NSCopying协议定义的copyWithZone:方法返回的对象
 *  @return copy出的对象
 */
- (id)copy;

/**
 *  @author Arbboter, 15-01-15 23:01:49
 *  由NSMutableCopying协议定义的mutableCopyWithZone:方法返回的对象
 *  @return copy出的对象
 */
- (id)mutableCopy;

/** copy协议 */
+ (id)copyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
+ (id)mutableCopyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;

/** 释放销毁对象 */
- (void)dealloc;

/** 其他的方法这里不予讨论了 */

@end

首先需要注意的两个方法是loadinitialize的调用次序和时机。load是当类的头文件或者其扩展被import的时候就会调用,不管有没有使用该类,而initialize是在类的方法被第一次调用前会被调用。更多的细节问题比较烦,代码中的注释相对二样更详尽一点。


接下来来看看NSObject的一个唯一成员变量isa,该变量的类型是Class。通过查看Class的定义以及相关的类型定义,你会发现一个很有趣的事实,如下所示:

/** Objective-C对象的定义 */
@interface NSObject <NSObject>
{
    /** 指向当前类的实例所在的类的一个指针 */
    Class isa  OBJC_ISA_AVAILABILITY;
}

/* 一些方法的定义 */

@end

/** Objective-C对象的结构体的定义
 *  用于保存对象的状态(实例变量)
 */
struct objc_object
{
    Class isa  OBJC_ISA_AVAILABILITY;
};

/** Objective-C对象的类的定义
 *  用于保存对象的方法
 */
struct objc_class
{
    Class isa  OBJC_ISA_AVAILABILITY;
    /** 以下省略了oc1.0版本定义的部分 */
} OBJC2_UNAVAILABLE;

typedef struct objc_class *Class; // 指向类结构的指针
typedef struct objc_object *id;   // 指向Objective-C对象结构体的指针
从上面的定义我们发现了之前所提到的Class和我们熟悉的id的定义,同时发现了一个奇怪的现象。结构体objc_object、objc_class和NSObject的成员变量居然一模一样,都是
Class isa  OBJC_ISA_AVAILABILITY;

这是为什么呢?大家可以看看《Objective-C的对象模型分析》这篇文章,然后再回头看这个问题或许就能看出一些名堂了。其实NSObeject是Objective-C的几乎全部对象的基类,该类定义了类的状态信息(变量)和方法(类方法和实例方法),而Class是用于指向保存NSObeject的方法信息的指针,id用于保存NSObject的状态信息的指针,两个一起协作一起更好地描述NSObject。每个Objective-C的对象的成员变量isa指向的是这个对象的类信息,同时isMemberOfClass:方法就就是根据isa信息来判断的。


通过分析,我们可以发现类其实也是一个对象。当我们定义一个类的时候,实际上定义了两个类,一个类是我们看得到的类,一个类是我们看不到的同名元类,而我们看到的类就是该元类的对象。(具体可看看之前提到的那篇文章)


(没思路,理清了再来补充)


深入学习Objective-C的NSObject