Those who are proficient in OC must be familiar with the above picture. Yes, this is Apple’s official instance object, class, and metaclass relationship diagram. It vividly shows the relationship between isa, superclass, and metaclass. Inheritance relationship
Having seen the implementation principle of the OC class, we can know that the OC class is inherited from objc_class, NSObject is the type of OC, and objc_object is the type of c;
The structure type objc_class inherits from the objc_object type, where objc_object is also a structure and has an isa attribute, so objc_class also has an isa attribute;
The isa in NSObject is defined by Class at the bottom, and the bottom code of class comes from the objc_class type, so NSObject also has the isa attribute;
NSObject is a class, use it to initialize an instance object objc, objc satisfies the characteristics of objc_object (that is, has isa attribute), mainly because isa is inherited from objc_class by NSObject, and objc_class inherits from objc_object, and objc_object has isa attribute. So the object has an isa, which means that it points to the current objc_object;
objc_object is the current root object, all objects have such a characteristic objc_object, that is, have the isa attribute.
So is the same with classes in Swift? What is the structure of a class in Swift? What about its underlying implementation?
Class structure
1. Structure
In the previous blog, we analyzed the instance object of Swift. For instance objects, its essence is a HeapObject structure with a default memory size of 16 bytes (there are two attributes: metadata 8 bytes + refCounts 8 bytes );
After understanding the memory allocation of HeapObject, you should notice a Metadata. Its type is HeapMetadata. Let’s take a look at its specific memory structure.
Two, HeapMetadata type analysis
Enter the HeapMetadata definition, which is an alias of TargetHeapMetaData type, and receives a parameter Inprocess:
Enter TargetHeapMetaData definition, which is essentially a template type, which defines some required data structures. There are no attributes in this structure, only the initialization method, and a parameter of MetadataKind type is passed in, where kind is the passed Inprocess;
constexpr TargetHeapMetadata(MetadataKind kind) is the initialization method, and the types of kind are as follows:
name
value
Class
0x0
Struct
0x200
Enum
0x201
Optional
0x202
ForeignClass
0x203
Opaque
0x300
Tuple
0x301
Function
0x302
Existential
0x303
Metatype
0x304
ObjCClassWrapper
0x305
ExistentialMetatype
0x306
HeapLocalVariable
0x400
HeapGenericLocalVariable
0x500
ErrorObject
0x501
LastEnumerated
0x7FF
Enter TargetMetaData definition, there is a kind attribute, the type of kind is the previously passed Inprocess. It can be concluded from this that for kind, its type is unsigned long, which is mainly used to distinguish which type of metadata;
From the definition of TargetHeapMetadata and TargetMetaData, it can be seen that the type of the parameter kind in the initialization method is MetadataKind;
Enter the MetadataKind definition, there is a #include "MetadataKind.def", click to enter, which records all types of metadata;
Go back to the TargetMetaData structure definition, find the method getClassObject, in this method to match kind, the return value is TargetClassMetadata type; if it is Class, directly force this (the current pointer, that is metadata) to ClassMetadata;
const TargetClassMetadata<Runtime>*getClassObject()const;
template<>inlineconst ClassMetadata *
Metadata::getClassObject()const{
// 匹配kindswitch(getKind()){
// 如果kind是classcase MetadataKind::Class:{
// Native Swift class metadata is also the class object.// 将当前指针强转为ClassMetadata类型return static_cast<const ClassMetadata *>(this);}case MetadataKind::ObjCClassWrapper:{
// Objective-C class objects are referenced by their Swift metadata wrapper.auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);return wrapper->Class;}// Other kinds of types don't have class objects.default:return nullptr;}}
Therefore, TargetMetadata and TargetClassMetadata are essentially the same, because in the memory structure, pointers can be converted directly, so it can be considered that the structure is actually TargetClassMetadata;
Enter TargetClassMetadata definition, inherited from TargetAnyClassMetadata, have the following attributes, which are part of the class structure:
When the kind of metadata is Class, there is the following inheritance chain:
The actual type returned by the current class is TargetClassMetadata, and there is only one attribute kind in TargetMetaData, and there are 4 attributes in TargetAnyClassMetaData, namely kind, superclass, cacheData, and data;
The attributes of the current Class stored in memory are composed of TargetClassMetadata attribute + TargetAnyClassMetaData attribute + TargetMetaData attribute, so the resulting metadata structure is as follows:
The instance object in OC is essentially a structure, which is created through the underlying objc_object, and the class is inherited from objc_class; the instance object in Swift is also a structure in nature, the type is HeapObject, which has one more refCounts than OC;
The methods in OC are stored in the methodList of the objc_class structure class_rw_t; the methods in swift are stored in metadata;
ARC in OC maintains a hash table; ARC in Swift has refCounts property inside the object.