# 12.类的实现与初始化源码解读

## 前言

在上一文中[runtime-objc\_msgSend](/wiki/ios/di-ceng/11.runtime-objc_msgsend.md)中我们有遇到这样一个重要的流程

```cpp
cls = realizeAndInitializeIfNeeded_locked(inst, cls, behavior & LOOKUP_INITIALIZE);
```

本文就将对`类的实现与初始化`，结合源码作深入探究。

```cpp
/***********************************************************************
* realizeAndInitializeIfNeeded_locked
如果类未实现就实现，如果未初始化就初始化
inst：是cls或者其子类的一个实例对象，或者nil
cls：需要初始化或者实现的类
initialize：true会初始化class，false跳过初始化
**********************************************************************/
static Class
realizeAndInitializeIfNeeded_locked(id inst, Class cls, bool initialize)
{
    runtimeLock.assertLocked();
    if (slowpath(!cls->isRealized())) {
        cls = realizeClassMaybeSwiftAndLeaveLocked(cls, runtimeLock);
    }

    if (slowpath(initialize && !cls->isInitialized())) {
        cls = initializeAndLeaveLocked(cls, inst, runtimeLock);
    }
    return cls;
}
```

> 本文基于 `objc4-818.2`源码

## 一、实现初始化的区别

这里你肯定和我一样有疑问：

* 初始化我大概知道是啥，实现是个什么鬼？有什么区别？

### 1.1 isRealized()

```cpp
bool isRealized() const {
    return !isStubClass() && (data()->flags & RW_REALIZED);
}
```

实际是判断当前类的`class_rw_t *data()`是否存在，及是否有标志位`RW_REALIZED`

### 1.2 isInitialized()

```cpp
bool isInitialized() {
    return getMeta()->data()->flags & RW_INITIALIZED;
}
```

实际是判断metaClass的`class_rw_t *data()`是否存在，及是否有标志位`RW_INITIALIZED`

## 一、实现类：realizeClassMaybeSwiftAndLeaveLocked

### 流程图

搭配源码及注释食用更加

![iOS底层-类的实现](/files/-Mdfn_2fzRLcQYQ1qBk3)

### 1.1 实现OC类

```cpp
static Class realizeClassWithoutSwift(Class cls, Class previously)
{
    runtimeLock.assertLocked();

    class_rw_t *rw;
    Class supercls;
    Class metacls;

    if (!cls) return nil;
    if (cls->isRealized()) {
        // 已经实现了的话，验证一下没问题就return
        validateAlreadyRealizedClass(cls);
        return cls;
    }
    ASSERT(cls == remapClass(cls));

    // fixme verify class is not in an un-dlopened part of the shared cache?
    auto ro = (const class_ro_t *)cls->data();
    // 是否是元类
    auto isMeta = ro->flags & RO_META;

    if (ro->flags & RO_FUTURE) {
        // TODO: 不太知道这个是啥意思
        // This was a future class. rw data is already allocated.
        rw = cls->data();
        ro = cls->data()->ro();
        ASSERT(!isMeta);
        cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
    } else {
        // 一般Class。创建rw
        // Normal class. Allocate writeable class data.
        rw = objc::zalloc<class_rw_t>();
        // 设置ro
        rw->set_ro(ro);
        // 设置标志位
        rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
        // 设置rw
        cls->setData(rw);
    }

    // 创建 cache
    cls->cache.initializeToEmptyOrPreoptimizedInDisguise();

#if FAST_CACHE_META
    if (isMeta) cls->cache.setBit(FAST_CACHE_META);
#endif

    /**
    选取在Class数组中的下标
    有个全局变量 objc_indexed_classes_count会递增
    全局数组用来保存Class Class objc_indexed_classes[1] = { nil };

    放入 objc_indexed_classes 是在
     */
    cls->chooseClassArrayIndex();

。。。

    // 父类
    supercls = realizeClassWithoutSwift(remapClass(cls->getSuperclass()), nil);
    // 元类
    metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil);

#if SUPPORT_NONPOINTER_ISA
    。。。
// SUPPORT_NONPOINTER_ISA
#endif

    // Update superclass and metaclass in case of remapping
    // 设置父类
    cls->setSuperclass(supercls);
    // 设置类的ISA为metaClass
    cls->initClassIsa(metacls);

    // Reconcile instance variable offsets / layout.
    // This may reallocate class_ro_t, updating our ro variable.
    /**
     存在父类并且不是元类
     调整成员变量偏移量/布局，可能会重新创建 ro，并更新成员变量
     */
    if (supercls  &&  !isMeta) reconcileInstanceVariables(cls, supercls, ro);

    // Set fastInstanceSize if it wasn't set already.
    cls->setInstanceSize(ro->instanceSize);

    // Copy some flags from ro to rw
    // 将一些标志位从ro复制到rw
    if (ro->flags & RO_HAS_CXX_STRUCTORS) {
        cls->setHasCxxDtor();
        if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) {
            cls->setHasCxxCtor();
        }
    }

    // Propagate the associated objects forbidden flag from ro or from
    // the superclass.
    if ((ro->flags & RO_FORBIDS_ASSOCIATED_OBJECTS) ||
        (supercls && supercls->forbidsAssociatedObjects()))
    {
        rw->flags |= RW_FORBIDS_ASSOCIATED_OBJECTS;
    }

    // Connect this class to its superclass's subclass lists
    if (supercls) {
        // 如果存在父类，添加到其子类列表中
        addSubclass(supercls, cls);
    } else {
        /**
         设置根类：全局变量 _firstRealizedClass

         ***********************************************************************
         * _firstRealizedClass
         * The root of all realized classes
         **********************************************************************
         static Class _firstRealizedClass = nil;

         */
        addRootClass(cls);
    }

    // Attach categories
    /***********************************************************************
    添加分类
    * Fixes up cls's method list, protocol list, and property list.
    **********************************************************************/
    methodizeClass(cls, previously);

    return cls;
}
```

### 1.2 实现Swift类

* 注意点
  * `Metaclasses` never have a `Swift initializer`.
  * `Root classes` never have a `Swift initializer`.
  * (These two together avoid initialization order problems at the root.)
    * 这两条避免了初始化的顺序错乱的问题
  * 没有`initializer的Swift类`也不存在拥有`initializer的父类`
    * 在`realizeClassWithoutSwift()`内无须扫描父类

```cpp
static Class realizeSwiftClass(Class cls)
{
。。。

    if (auto init = cls->swiftMetadataInitializer()) {
        // 有Swift元数据初始化方法
        。。。
        Class newcls = init(cls, nil);

        if (cls != newcls) {
            mutex_locker_t lock(runtimeLock);
            addRemappedClass(cls, newcls);
        }
        return newcls;
    }
    else {
        // 没有Swift初始化方法，直接调用OC的
        mutex_locker_t lock(runtimeLock);
        return realizeClassWithoutSwift(cls, nil);
    }
}
```

## 二、初始化类：initializeAndLeaveLocked

相比Realize的流程，初始化的流程相对简单。我画了个流程图。

![iOS底层-类的初始化](/files/-Mdfn_2iV6U3g5gEGciG)

## 三、总结

* Realize
  * 主要完成类的基础结构的搭建
    * 如`ISA链`和`继承链`，`rw`，`ro`
* Initialize
  * 找到`非元类`的Class
  * `标志位`处理
  * `+initialize`方法调用


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/di-ceng/12.-lei-de-shi-xian-yu-chu-shi-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
