天天看點

Runtime Basics of Objective-C

Runtime Components

The Objective-C runtime system has two main components: the compiler and the runtime library. Let’s take out a magnifying glass to examine these in more detail and see how they are used to implement the runtime system.

Compiler

In Chapter 5, you briefly reviewed the general process of Objective-C source code compilation. As depicted in Figure 5-1, the compilation process takes input Objective-C source files and proceeds, in multiple phases (consisting of lexical analysis, syntax analysis, code generation and optimization, assembly, and linking operations), to produce the output binaries that form an executable program.

Just as the C standard library provides a standard API and implementation for the C programming language, the runtime library provides a standard API and implementation for the object-oriented features of Objective-C. This library is linked (during the linking phase) to all Objective-C programs. It’s the job of the compiler to take your input source code and generate code that uses the runtime library to produce a valid, executable Objective-C program.

Both the object-oriented elements and dynamic features of the Objective-C language are implemented by the runtime system. Together, this consists of the following:

  • Class elements (interface, implementation, protocols, categories, methods, properties, instance variables)
  • Class instances (objects)
  • Object messaging (including dynamic typing and binding)
  • Dynamic method resolution
  • Dynamic loading
  • Object introspection

In summary, when the compiler parses Objective-C source code that uses these language elements and features, it generates code with the appropriate runtime library data structures and function calls to implement the language-specified behaviors. To clarify how this works, let’s look at a few examples that demonstrate how the compiler generates code for Objective-C classes and objects, and how it performs object messaging.

Object Messaging Code Generation

When the compiler parses an object message (a message send expression), such as

[receiver message]      

for example, it generates code that calls the runtime library function objc_msgSend(). This function takes as its input parameters the receiver and the selector of the message, along with any parameters passed in the message. Thus the compiler converts each messaging expression in the source code (i.e., of the form [receiver message]) to a call on the runtime library messaging function objc_msgSend(...), passing along any supplied parameters to the call. Each message is dynamically resolved, meaning that the message receiver type and the actual method implementation to be invoked are determined at runtime. For each class and object in the source code, the compiler builds the data structures required to perform object messaging.

Class and Object Code Generation

When the compiler parses Objective-C code containing class definitions and objects, it generates corresponding runtime data structures. An Objective-C class corresponds to a runtime library Classdata type. According to the Apple Runtime Reference, the Class data type is a pointer to an opaque type with an identifier of objc_class.

typedef struct objc_class *Class;      

An opaque data typeis a C struct type that is incompletely defined in its interface. Opaque types provide a form of data hiding, in that their variables can only be accessed through functions designed specifically for them. Runtime library functions are used to access the variables of the Class (i.e.,objc_class) data type.

Just as Objective-C classes have a runtime data type, Objective-C objects also have a corresponding runtime data type. When the compiler parses Objective-C code for objects, it generates code that creates a runtime object type. This data type, defined in Listing 8-1, is a C struct with an identifier of objc_object.

Listing 8-1.  objc_object Data Type

struct objc_object
{
  Class isa;
  /* ...variable length data containing instance variable values...  */
};      

When you create an object, memory is allocated for an objc_object type that consists of an isapointer directly followed by the data for the instance variables of the object.

Note that, as with the Class data type, the objc_object type contains a variable named isa of typeClass; in other words, a pointer to a variable of type objc_class. In fact, the runtime data type for all Objective-C objects and classes begin with an isa pointer. The runtime equivalent for the Objective-C id type is a C struct defined as a pointer to an objc_object, for example.

Listing 8-2.  id Type Definition

typedef struct objc_object
{
  Class isa;
} *id;      

In other words, an id is just a pointer to a C struct with the identifier objc_object. The runtime data structure for Objective-C block objects follows the same convention, thereby enabling them to also be properly managed by the runtime system.

Runtime Library

The Apple Objective-C runtime library implements the object-oriented features and dynamic properties of the Objective-C language. For the most part, the runtime library acts behind the scenes, but it also includes a public API that enables it to be used directly in your code.

This API is expressed in C and consists of a set of functions, data types, and language constants. You learned about some of the key runtime data types (e.g., objc_object, objc_class) and used a few of these functions in the previous section. Overall, the runtime library data types can be grouped as follows:

  • Class definition data structures (class, method, ivar, category, IMP, SEL, etc.)
  • Instance data types (id, objc_object, objc_super)
  • Values (BOOL)

The functions fall into the following categories:

  • Object messaging
  • Class functions
  • Instance functions
  • Protocol functions
  • Method functions
  • Property functions
  • Selector functions

The runtime library also defines several Boolean constants (YES, NO) and null values (NULL, nil, Nil).

The runtime library public API is declared in the runtime.h header file. Apple’s runtime library is available for examination at http://opensource.apple.com . It incorporates a variety of design elements and system services to provide excellent performance and extensibility as the Objective-C language evolves over time.