The Principles of Objective-C Runtime

Introduction : refers to the state of a program while it is running (or being executed). In other words, when you open a program and it runs on your computer, that program is in its runtime state. In some programming languages, reusable programs or instances are packaged or rebuilt into a . These instances can be linked or called by any program while they are running. : a relatively low-level pure C language API, part of a C language library, containing many low-level C language APIs. When we write OC code and the program runs, everything ultimately gets converted into C language code. is a dynamic language built on top of C with object-oriented features and a message-forwarding mechanism. This means it requires not just a compiler, but also a system to dynamically create classes and objects, and to send and forward messages. Runtime Data Structures Reference: Objective-C Runtime — Part 1: Classes and Objects In , using syntax does not immediately execute the code of 's method. Instead, it sends a to . This message may be handled by , forwarded to another object, or silently ignored. In practice, is compiled by the compiler into: SEL is the data type of the second parameter of , representing a method selector. Its data structure in : In essence, it is a C string mapped to a method. You can obtain an -type method selector using the Objective-C compiler directive or the runtime function . If you know the method name that corresponds to a , you can convert the to a string using and print it with . id The data type of the first parameter of is . is a generic pointer type that can represent any object. Its data structure in : is essentially a pointer to an struct. It contains a member; by following the pointer you can trace all the way to the class the object belongs to. Note: According to Apple's official documentation Key-Value Observing Implementation Details, key-value observing is implemented using isa-swizzling. The pointer is modified at runtime to point to an intermediate class rather than the true class. Therefore, you should not use the pointer to determine class relationships; use the class method instead. Class The data type of the pointer is . represents the class that an object belongs to. In : You can see that is simply a pointer to an struct. Let's look at the definition of in : Note: is a macro Apple uses to constrain the runtime version of the Objective-C system, primarily for backward compatibility with pre-Objective-C 2.0 code. We can still extract useful information from it. - isa: Represents the of a object — i.e., the MetaClass. In object-oriented design, everything is an object, and is itself an object in this design. Evidence can be found in , where is defined as: This confirms that the struct also inherits from , meaning is indeed an object in this design. is also a , so it has its own and pointers like any other class, as shown below: Solid lines represent pointers; dashed lines represent pointers. A few key points: 1. () is just . has no superclass, so ()'s points to nil. 2. Every has an pointer pointing to its unique . 3. ()'s points to () — i.e., — forming a loop. 4. Every 's pointer points to (). - superclass: The superclass. If this class is already the topmost root class, this is . - version: Class version info, default 0. - info: Some bit flags used at runtime. - instancesize: The size of the class's instance variables. - ivars: Represents multiple member variables; points to an struct. is essentially a linked list storing multiple entries, where each struct stores information about a single member variable. - methodLists: Represents the method list; points to a double pointer to . You can dynamically add instance methods by modifying — this is how Categories work, and also explains why Categories cannot add properties. Similarly, is a linked list storing multiple entries, where each struct stores information about a specific method. - objccache: Used to cache frequently accessed methods; points to an struct, which will be covered in more detail later. - protocols: The protocols the class conforms to. - Method: Represents a method in a class definition. In : is a pointer to an struct, which stores the method name (), method type encoding (), and method implementation (). The type of is — a function pointer. - Ivar: Represents an instance variable in a class. In : is a pointer to an struct containing the variable name (), variable type (), and other info. - IMP: As mentioned above when discussing , is fundamentally a function pointer that points to the method implementation. In : When you send a message to an object, this function pointer specifies the method's implementation and ultimately executes that code. This lets you bypass the message-passing stage and jump directly to a specific method implementation. - Cache**: As the name suggests, is mainly used for caching. What does it cache? Let's look at its definition in : is essentially a linked list of entries, primarily used to optimize method dispatch performance. When an object calls method , the runtime first uses the object's pointer to find the corresponding class, then searches for the method. If not found, it follows to search the parent class's , and so on until the method is found and called. If still not found, message forwarding may occur, or the message may be ignored. However, this lookup approach is inefficient — typically only about 20% of a class's methods account for 80% of all calls. Using to cache frequently called methods means method lookup checks the first, and only falls back to if needed. Supplemental Notes on Metaclasses () and : Core rule: An instance object's points to its class; the class's points to its metaclass. In plain terms: instance methods are recorded in the ; class methods are recorded in the . That is, information lives in the , and information lives in the . The inheritance chain for class instance variables: Every object is fundamentally an instance of a class. The class defines the list of member variables and methods. An object points to its class via the object's pointer. Every class is fundamentally an object — a class is actually an instance of its metaclass (). The metaclass defines the list of class methods. A class points to its metaclass via the class's pointer. All metaclasses ultimately inherit from a root metaclass, whose pointer points to itself, forming a closed loop. Code: All code from this post can be found on my GitHub .