A brief analysis of Objective-c Runtime class and Object tutorial

Source: Internet
Author: User
Tags class definition data structures inheritance instance method

The advantage of the

Objective-c language is that we are more flexible when writing code, such as we can forward the message to the object we want, or swap the implementation of a method at random.

This feature means that objective-c requires not only a compiler, but also a run-time system to execute compiled code. For objective-c, this run-time system is like an operating system: it allows all work to function properly. This run-time system is OBJC Runtime. OBJC runtime is actually a runtime library, it is basically written in C and remit, this library makes C language have object-oriented ability. The

Runtime library mainly does the following things:
    1, encapsulation: In this library, objects can be represented in C-language structures, and methods can be implemented with C functions, plus some additional features. After these structures and functions are encapsulated by the runtime function, we can create, check, and modify classes, objects, and their methods when the program is run.
    2, to find the final code of execution for the method: when the program executes [object DoSomething], it sends a message to the message Receiver (object) (dosomething), Runtime responds differently depending on whether the message recipient responds to the message. This will be covered in more detail later. There are currently two versions of the

Objective-c Runtime: Modern runtime and Legacy runtime. The modern Runtime covers 64-bit Mac OS X Apps, and IOS apps,legacy Runtime is used earlier for 32-bit Mac OS X Apps, which means it's OK to use it.

In this series of articles, we will look at the basics of how runtime works, and how it can be leveraged to make our programs more flexible. In this article, let's take a look at the classes and objects, which is the object-oriented basis, and we'll see how the classes are implemented in runtime. The

class and object infrastructure data structure

class

Objective-c classes are represented by class types. It is actually a pointer to a OBJC_CLASS structure. It is defined as follows:

The code is as follows Copy Code
typedef struct OBJC_CLASS * class;

See the definition of the OBJC_CLASS structure in objc/runtime.h as follows:

The code is as follows Copy Code
struct Objc_class {


Class Isa objc_isa_availability;





#if!__objc2__


Class Super_class objc2_unavailable; Parent class


const char *name objc2_unavailable; Class name


Long version objc2_unavailable; The version information for the class, default is 0


Long info objc2_unavailable; Class information for some bit identities that are used during the runtime


Long Instance_size objc2_unavailable; The instance variable size of the class


struct Objc_ivar_list *ivars objc2_unavailable; The member variable list of the class


struct Objc_method_list **methodlists objc2_unavailable; A linked list of method definitions


struct Objc_cache *cache objc2_unavailable; Method Cache


struct Objc_protocol_list *protocols objc2_unavailable; Protocol Chain List


#endif





} objc2_unavailable;


In this definition, the following fields are of interest to US

    1.isa: It should be noted that in objective-c, all classes themselves are an object, The object's class also has an Isa pointer that points to the Metaclass (the Meta Class), which we'll introduce later.
    2.super_class: A parent class that points to the class, and Super_class null if the class is already the topmost root class (such as NSObject or Nsproxy).
    3.cache: Used to cache recently used methods. When a recipient object receives a message, it looks for an object that responds to the message based on the ISA pointer. In practice, this object has only a subset of the methods that are commonly used, and many methods are rarely used or are not used at all. In this case, if every time the message comes, we are traversing the methodlists, the performance is bound to be very poor. At this time, the cache came in handy. Every time we call a method, this method will be cached in the cache list, the next time the runtime will first go to the cache to find, if the cache does not go to Methodlists to find methods. This makes calls to methods that are often used, but increases the efficiency of the invocation.
    4.version: We can use this field to provide version information for the class. This is useful for serializing objects, but it lets us identify changes in the layout of instance variables in different class-defined versions.

for cache, we use the following example to illustrate its execution process:

The code is as follows Copy Code
Nsarray *array = [[Nsarray alloc] init];

The process is:

[Nsarray Alloc] is executed first. Because Nsarray no +alloc method, so go to the parent class NSObject to find.
Detects whether NSObject responds to the +alloc method, discovers the response, detects the Nsarray class, starts allocating memory space based on the amount of memory space it needs, and then points the ISA pointer to the Nsarray class. At the same time, +alloc is also added to the cache list.
Next, the-init method is executed, and if the Nsarray responds to the method, it is added directly to the cache, and the parent class is searched if it does not respond.
In later operations, if an array is created in this way [[Nsarray alloc] init], the corresponding method is directly fetched from the cache and called directly.

Objc_object and IDs

Objc_object is a struct that represents an instance of a class, which is defined as follows (OBJC/OBJC.H):

  code is as follows copy code
struct objc_ Object {
    Class isa  objc_isa_availability;
};

typedef struct OBJC_OBJECT *id;

As you can see, this structure has only one font, that is, the ISA pointer to its class. Thus, when we send a message to a Objective-c object, the Run-time library finds the class to which the instance object belongs, based on the ISA pointer of the instance object. The runtime library looks for the selector-pointing method for the message in the class's method list and the parent class's list of methods. This method is run when found.

When you create an instance object of a particular class, the allocated memory contains a OBJC_OBJECT data structure, followed by a class's instance variable. The Alloc and Allocwithzone of the NSObject class: Methods use function class_createinstance to create OBJC_OBJECT data structures.

In addition to our common ID, it is a pointer to a objc_object struct type. Its presence allows us to implement some operations similar to generics in C + +. Objects of this type can be converted to any object, somewhat similar to the function of a void pointer type in C language.
Objc_cache

This refers to the cache field in the Objc_class structure body, which is used for caching the invoked method. This field is a pointer to the OBJC_CACHE structure, which is defined as follows:

The code is as follows Copy Code
struct objc_ Cache {
    unsigned int mask/* Total = mask + 1 */        &NB sp;        objc2_unavailable;
    unsigned int occupied                                      objc2_unavailable;
    Method buckets[1]                                          objc2_unavailable;
};

The fields of the structure are described as follows:
Mask: An integer that specifies the total number of cached bucket allocated. During method lookup, Objective-c runtime uses this field to determine the index position at which to begin a linear lookup array. The pointer to the method selector does an and bitwise operation with the field (index = (mask & selector)). This can be used as a simple hash hash algorithm.
Occupied: An integer that specifies the total number of cached bucket that are actually occupied.
Buckets: An array that points to the method data structure pointer. This array may contain no more than mask+1 elements. It should be noted that the pointer may be NULL, indicating that the cache bucket is not occupied, and that the bucket of the other occupied may be discontinuous. This array may grow over time.

Meta classes (META Class)

As we mentioned above, all classes themselves are also objects, and we can send messages to this object (that is, call the class method). Such as:

The code is as follows Copy Code
Nsarray *array = [Nsarray array];

In this case, the +array message is sent to the Nsarray class, and this Nsarray is an object. Since it is an object, it is also a objc_object pointer that contains an ISA pointer to its class. So here's the question, what does this ISA pointer point to? In order to invoke the +array method, the ISA pointer for this class must point to a objc_class struct that contains these class methods. This leads to the concept of Meta-class

Meta-class is the class of a class object.

When we send a message to an object, runtime looks up the method in the list of methods for the class to which the object belongs, and when sending a message to a class, it is found in the Meta-class list of methods for that class. The

Meta-class is important because it stores all the class methods of a class. Each class will have a separate meta-class, because the class method of each class is basically impossible to be identical.

In Depth, Meta-class is also a class, and can send a message to it, so what does its Isa point to? In order not to allow this structure to extend indefinitely, Objective-c's designers let all Meta-class Isa point to the base class Meta-class as their owning class. That is, any meta-class under the NSObject inheritance system uses the Meta-class of NSObject as its own class, whereas the base class's Meta-class Isa pointer points to itself. This creates a perfect closed loop.

By using the above description, coupled with the analysis of the Super_class pointer in the OBJC_CLASS structure, we can describe an inheritance system for classes and corresponding Meta-class classes, as shown in the following illustration:



for NSObject inheritance systems, the instance method is valid for all instances, classes, and Meta-class in the system. , and the class method is valid for all the classes and Meta-class in the system.

So much, let's write an example:

The code is as follows Copy Code
void Testmetaclass (id self, SEL _cmd) {





NSLog (@ "This objcet is%p", self);


NSLog (@ "class is%@, Super class is%@", [Self Class], [self superclass]);





Class Currentclass = [self class];


for (int i = 0; i < 4; i++) {


NSLog (@ "Following the ISA pointer%d times gives%p", I, Currentclass);


Currentclass = Objc_getclass ((__bridge void *) currentclass);


}





NSLog (@ "NSObject ' class is%p", [NSObject class]);


NSLog (@ "NSObject ' Meta class is%p", Objc_getclass ((__bridge void *) [NSObject class]);


}





#pragma mark-





@implementation Test





-(void) Ex_registerclasspair {





Class Newclass = Objc_allocateclasspair ([Nserror class], "TestClass", 0);


Class_addmethod (Newclass, @selector (Testmetaclass), (IMP) Testmetaclass, "v@:");


Objc_registerclasspair (Newclass);





id instance = [[Newclass alloc] initwithdomain:@ "some domain" code:0 userinfo:nil];


[Instance Performselector: @selector (Testmetaclass)];


}





@end




This example creates a nserror subclass of TestClass at run time, and then adds a method testmetaclass to the subclass, which implements the Testmetaclass function.





After running, the print result is





2014-10-20 22:57:07.352 mountain[1303:41490] This objcet is 0x7a6e22b0


2014-10-20 22:57:07.353 mountain[1303:41490] Class is Teststringclass, Super Class is Nserror


2014-10-20 22:57:07.353 mountain[1303:41490] Following the ISA pointer 0 times gives 0X7A6E21B0


2014-10-20 22:57:07.353 mountain[1303:41490] Following the ISA pointer 1 times gives 0x0


2014-10-20 22:57:07.353 mountain[1303:41490] Following the ISA Pointer 2 times gives 0x0


2014-10-20 22:57:07.353 mountain[1303:41490] Following the ISA pointer 3 times gives 0x0


2014-10-20 22:57:07.353 mountain[1303:41490] NSObject ' s class is 0xe10000


2014-10-20 22:57:07.354 mountain[1303:41490] nsobject ' Meta class is 0x0





In the For loop, we get the object's Isa through Objc_getclass, and print it out, which goes back to NSObject's meta-class. Analysis of the print results, you can see the last pointer to the address is 0x0, that is, NSObject's Meta-class class address.





Notice here that we can't get meta-class in a class object by invoking the class method, it's just a return class.

Class vs. Object manipulation functions

Runtime provides a number of functions to manipulate classes and objects. Most of the action methods for a class are prefixed by class, whereas the object's methods of operation are mostly prefixed with OBJC or object_. Below we will discuss the use of these methods based on the purpose of these methods.

Class-Dependent Action function

We can go back and look at the definition of Objc_class, Runtime provides a method of manipulating the class mainly for each field in the structure. Here are some of the functions that we'll describe separately. And at the end, illustrate the specific usage of these functions with examples.

class name (name)





The functions of a class name operation are:





Gets the class name of the class


const char * CLASS_GETNAME (class CLS);





For the Class_getname function, if the incoming CLS is nil, a character string is returned.


Parent class (Super_class) and Meta Class (Meta-class)





The functions of the parent class and the Meta class operations are mainly:





Gets the parent class of the class


Class Class_getsuperclass (class CLS);





To determine whether a given class is a meta class


BOOL Class_ismetaclass (class CLS);





The Class_getsuperclass function, which returns nil when the CLS is nil or the CLS is the root class. But usually we can use the NSObject class superclass method to achieve the same goal.





The Class_ismetaclass function, which returns YES if the CLS is a class, or no if no or the incoming CLS is nil.


Instance variable size (instance_size)





The function of the instance variable size operation is:





Get instance Size


size_t class_getinstancesize (class CLS);





member variables (ivars) and properties





In Objc_class, the information of all the member variables and attributes is placed in the ivars of the list. Ivars is an array in which each element of the array is a pointer to the Ivar (variable information). Runtime provides a rich function to manipulate this field. In general, it can be divided into the following categories:





1. Member variable operation function, mainly contains the following functions:





Gets information about the specified name instance member variable in the class


Ivar class_getinstancevariable (class cls, const char *name);





Get information about a class member variable


Ivar class_getclassvariable (class cls, const char *name);





Add Member Variable


BOOL Class_addivar (class cls, const char *name, size_t size, uint8_t alignment, const char *types);





Get the entire member variable list


Ivar * Class_copyivarlist (class cls, unsigned int *outcount);





The Class_getinstancevariable function, which returns a pointer (Ivar) to the OBJC_IVAR structure that contains the member variable information specified by name.





class_getclassvariable function, there is no information about the class variables in objective-c, and it is generally believed that OBJECTIVE-C does not support class variables. Note that the returned list does not contain the member variables and properties of the parent class.





OBJECTIVE-C does not support adding instance variables to existing classes, so no member variables can be added dynamically, either by the provided classes provided by the system library or by our custom classes. But how do we add a member variable to a class if we create it through the runtime? Then we can use the Class_addivar function. It should be noted, however, that this method can only be invoked between the Objc_allocateclasspair function and the Objc_registerclasspair. Also, this class cannot be a meta class. The least-byte alignment of a member variable is 1<<alignment. This depends on the type of Ivar and the architecture of the machine. If the type of the variable is a pointer type, then the log2 (sizeof (Pointer_type)) is passed.





The Class_copyivarlist function, which returns an array of information about member variables, in which each element is a pointer to the OBJC_IVAR structure that points to the member variable information. This array does not contain variables declared in the parent class. The Outcount pointer returns the size of the array. It is important to note that we must use free () to release the array.





2. Property manipulation functions, which consist mainly of the following functions:





Gets the specified property


objc_property_t Class_getproperty (class cls, const char *name);





Get Property List


objc_property_t * Class_copypropertylist (class cls, unsigned int *outcount);





To add a property to a class


BOOL Class_addproperty (class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int Attributec Ount);





Replace the properties of a class


void Class_replaceproperty (class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attrib Utecount);





This method is also for Ivars, but only those values that are attributes are manipulated. We will encounter these functions again when we introduce the properties.





3. In the Mac OS x system, we can use the garbage collector. Runtime provides several functions to determine whether an object's memory area can be scanned by the garbage collector to handle a strong/weak reference. These functions are defined as follows:





Const UINT8_T * Class_getivarlayout (class CLS);


void Class_setivarlayout (class cls, const uint8_t *layout);


Const UINT8_T * Class_getweakivarlayout (class CLS);


void Class_setweakivarlayout (class cls, const uint8_t *layout);





Typically, however, we do not need to invoke these methods voluntarily, and a reasonable layout is generated when Objc_registerclasspair is invoked. These functions are not described in detail here.

Method (Methodlists)

Method operations have the following functions:

  code is as follows copy code
//Add method
BOOL Class_addmethod (class cls, SEL name, IMP imp, const char *types);

//Get instance methods
Method Class_getinstancemethod (class CLS, SEL name);

//Get class methods
Method Class_getclassmethod (class CLS, SEL name);

//Get an array of all methods
Method * Class_copymethodlist (class cls, unsigned int *outcount);

//Implementation of alternative methods
IMP Class_replacemethod (class cls, SEL name, IMP imp, const char *types);

//Return the concrete implementation of the method
IMP Class_getmethodimplementation (class cls, SEL name);
IMP Class_getmethodimplementation_stret (class cls, SEL name); Whether the

//class instance responds to the specified selector
BOOL class_respondstoselector (class CLS, sel sel);


The implementation of the Class_addmethod overrides the method implementation of the parent class, but does not replace the existing implementation in this class, and if this class contains an implementation with the same name, the function returns No. If you want to modify an existing implementation, you can use Method_setimplementation. A Objective-c method is a simple C function that contains at least two parameters-self and _cmd. So, our implementation function (the function that the IMP parameter points to) requires at least two parameters, as follows:

The code is as follows Copy Code
void Mymethodimp (id self, SEL _cmd)
{
Implementation .....
}


Unlike a member variable, we can dynamically add a method to a class, regardless of whether the class already exists.

In addition, the parameter types is a character array that describes the parameter types passed to the method, which involves type encoding, which we'll cover later.

Class_getinstancemethod, Class_getclassmethod functions, unlike class_copymethodlist, these two functions search for the implementation of the parent class.

Class_copymethodlist function that returns an array of all instance methods, and if you need to get a class method, you can use Class_copymethodlist (Object_getclass (CLS), &count) ( An instance method of a class is defined within the Meta class. The list does not contain methods implemented by the parent class. The number of methods returned by the Outcount parameter. After getting to the list, we need to use the free () method to release it.

Class_replacemethod function, the behavior of the function can be divided into two types: If the method specified by name does not exist in the class, the method is added like the Class_addmethod function, and if the method specified by name already exists in the class, it is similar to the Method_ Setimplementation as an alternative to the implementation of the original method.

The Class_getmethodimplementation function, which is invoked when a message is sent to a class instance, and returns a pointer to the method implementation function. This function is faster than Method_getimplementation (Class_getinstancemethod (CLS, name)). The returned function pointer may be a function that points to the interior of the runtime, not necessarily the actual implementation of the method. For example, if a class instance cannot respond to selector, the returned function pointer will be part of the RUN-TIME message forwarding mechanism.

Class_respondstoselector functions, we usually use the respondstoselector of the NSObject class: or Instancesrespondtoselector: Methods to achieve the same purpose.

Protocol (Objc_protocol_list)

Protocol-related operations include the following functions:

The code is as follows Copy Code
Add protocol
BOOL Class_addprotocol (class cls, Protocol *protocol);

Returns whether the class implements the specified protocol
BOOL Class_conformstoprotocol (class cls, Protocol *protocol);

Returns a list of protocols implemented by a class
Protocol * Class_copyprotocollist (class cls, unsigned int *outcount);


The Class_conformstoprotocol function can be substituted using the Conformstoprotocol: Method of the NSObject class.

The Class_copyprotocollist function returns an array, which we need to manually release using free ().

Versions (version)

Version-related operations include the following functions:

The code is as follows Copy Code
Get version number
int class_getversion (class CLS);

Set version number
void Class_setversion (class cls, int version);

Other

Runtime also provides two functions for use by corefoundation Tool-free bridging, namely:

Class objc_getfutureclass (const char *name);
void Objc_setfutureclass (Class cls, const char *name);

Usually we don't use these two functions directly.

Instance (Example)

With a number of functions listed above, let's take a look at the instance effects of these functions:

The code is as follows Copy Code
//-----------------------------------------------------------


MyClass.h





@interface Myclass:nsobject <nscopying, nscoding>





@property (nonatomic, strong) Nsarray *array;





@property (nonatomic, copy) NSString *string;





-(void) method1;





-(void) method2;





+ (void) classMethod1;





@end





//-----------------------------------------------------------


Myclass.m





#import "MyClass.h"





@interface MyClass () {


Nsinteger _instance1;





NSString * _INSTANCE2;


}





@property (nonatomic, assign) Nsuinteger integer;





-(void) Method3witharg1: (Nsinteger) arg1 arg2: (NSString *) arg2;





@end





@implementation MyClass





+ (void) ClassMethod1 {





}





-(void) Method1 {


NSLog (@ "Call method Method1");


}





-(void) Method2 {





}





-(void) Method3witharg1: (Nsinteger) arg1 arg2: (NSString *) arg2 {





NSLog (@ "arg1:%ld, arg2:%@", arg1, arg2);


}





@end





//-----------------------------------------------------------


Main.h





#import "MyClass.h"


#import "MySubClass.h"


#import <objc/runtime.h>





int main (int argc, const char * argv[]) {


@autoreleasepool {





MyClass *myclass = [[MyClass alloc] init];


unsigned int outcount = 0;





Class cls = Myclass.class;





Class name


NSLog (@ "Class name:%s", Class_getname (CLS));





NSLog (@ "==========================================================");





Parent class


NSLog (@ "Super Class Name:%s", Class_getname (Class_getsuperclass (CLS)));


NSLog (@ "==========================================================");





Whether it is a meta class


NSLog (@ "MyClass is%@ a Meta-class" (Class_ismetaclass (CLS) @ "": @ "not"));


NSLog (@ "==========================================================");





Class Meta_class = Objc_getmetaclass (Class_getname (CLS));


NSLog (@ "%s ' s Meta-class is%s", Class_getname (CLS), Class_getname (Meta_class));


NSLog (@ "==========================================================");





Variable instance size


NSLog (@ "Instance size:%zu", Class_getinstancesize (CLS));


NSLog (@ "==========================================================");





Member variable


Ivar *ivars = class_copyivarlist (CLS, &outcount);


for (int i = 0; i < Outcount; i++) {


Ivar Ivar = ivars[i];


NSLog (@ "instance variable ' s name:%s at index:%d", Ivar_getname (Ivar), I);


}





Free (ivars);





Ivar string = class_getinstancevariable (CLS, "_string");


if (string!= NULL) {


NSLog (@ "Instace variable%s", Ivar_getname (string));


}





NSLog (@ "==========================================================");





Property action


objc_property_t * Properties = class_copypropertylist (CLS, &outcount);


for (int i = 0; i < Outcount; i++) {


objc_property_t property = Properties[i];


NSLog (@ "Property ' Name:%s", property_getname);


}





Free (properties);





objc_property_t array = class_getproperty (CLS, "array");


if (array!= NULL) {


NSLog (@ "Property%s", Property_getname (array));


}





NSLog (@ "==========================================================");





Method action


Method *methods = Class_copymethodlist (CLS, &outcount);


for (int i = 0; i < Outcount; i++) {


Method method = Methods[i];


NSLog (@ "method ' s signature:%s", Method_getname (method));


}





Free (methods);





Method method1 = Class_getinstancemethod (CLS, @selector (METHOD1));


if (method1!= NULL) {


NSLog (@ "method%s", Method_getname (METHOD1));


}





Method Classmethod = Class_getclassmethod (CLS, @selector (CLASSMETHOD1));


if (Classmethod!= NULL) {


NSLog (@ "class method:%s", Method_getname (Classmethod));


}





NSLog (@ "MyClass is%@ responsd to Selector:method3WithArg1:arg2:", Class_respondstoselector (CLS, @selector ( METHOD3WITHARG1:ARG2:)? @ "": @ "not");





Imp imp = class_getmethodimplementation (CLS, @selector (METHOD1));


Imp ();





NSLog (@ "==========================================================");





Agreement


Protocol * __unsafe_unretained * protocols = Class_copyprotocollist (CLS, &outcount);


Protocol * PROTOCOL;


for (int i = 0; i < Outcount; i++) {


protocol = protocols[i];


NSLog (@ "protocol name:%s", Protocol_getname (protocol));


}





NSLog (@ "MyClass is%@ responsed to protocol%s", Class_conformstoprotocol (CLS, protocol) @ "": @ "not", Protocol_getname ( protocol));





NSLog (@ "==========================================================");


}


return 0;


}


The output of this procedure is as follows:

The code is as follows Copy Code
2014-10-22 19:41:37.452 runtimetest[3189:156810] class Name:myclass


2014-10-22 19:41:37.453 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.454 runtimetest[3189:156810] Super class Name:nsobject


2014-10-22 19:41:37.454 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.454 runtimetest[3189:156810] MyClass is not a meta-class


2014-10-22 19:41:37.454 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.454 runtimetest[3189:156810] MyClass ' s meta-class is MyClass


2014-10-22 19:41:37.455 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.455 runtimetest[3189:156810] instance size:48


2014-10-22 19:41:37.455 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.455 runtimetest[3189:156810] instance variable ' s name: _instance1 at index:0


2014-10-22 19:41:37.455 runtimetest[3189:156810] instance variable ' s name: _instance2 at Index:1


2014-10-22 19:41:37.455 runtimetest[3189:156810] instance variable ' s name: _array at Index:2


2014-10-22 19:41:37.455 runtimetest[3189:156810] instance variable ' s name: _string at Index:3


2014-10-22 19:41:37.463 runtimetest[3189:156810] instance variable ' s name: _integer at Index:4


2014-10-22 19:41:37.463 runtimetest[3189:156810] instace variable _string


2014-10-22 19:41:37.463 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.463 runtimetest[3189:156810] property ' s Name:array


2014-10-22 19:41:37.463 runtimetest[3189:156810] property ' s name:string


2014-10-22 19:41:37.464 runtimetest[3189:156810] property ' s Name:integer


2014-10-22 19:41:37.464 runtimetest[3189:156810] Property array


2014-10-22 19:41:37.464 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.464 runtimetest[3189:156810] method ' s SIGNATURE:METHOD1


2014-10-22 19:41:37.464 runtimetest[3189:156810] method ' s SIGNATURE:METHOD2


2014-10-22 19:41:37.464 runtimetest[3189:156810] method ' s SIGNATURE:METHOD3WITHARG1:ARG2:


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s Signature:integer


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s Signature:setinteger:


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s Signature:array


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s signature:string


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s signature:setstring:


2014-10-22 19:41:37.465 runtimetest[3189:156810] method ' s Signature:setarray:


2014-10-22 19:41:37.466 runtimetest[3189:156810] method ' s signature:. cxx_destruct


2014-10-22 19:41:37.466 runtimetest[3189:156810] Method method1


2014-10-22 19:41:37.466 runtimetest[3189:156810] class Method:classmethod1


2014-10-22 19:41:37.466 runtimetest[3189:156810] MyClass is RESPONSD to SELECTOR:METHOD3WITHARG1:ARG2:


2014-10-22 19:41:37.467 runtimetest[3189:156810] Call method method1


2014-10-22 19:41:37.467 runtimetest[3189:156810] ==========================================================


2014-10-22 19:41:37.467 runtimetest[3189:156810] protocol name:nscopying


2014-10-22 19:41:37.467 runtimetest[3189:156810] protocol name:nscoding


2014-10-22 19:41:37.467 runtimetest[3189:156810] MyClass is responsed to protocol nscoding


2014-10-22 19:41:37.468 runtimetest[3189:156810] ==========================================================


dynamically creating classes and objects

  code is as follows copy code
runtime is that it can run Class and objects are created when the The
dynamically creating classes

Dynamically creating classes involves several functions:

//Creating a new class and Meta class
Class Objc_allocateclasspair (class superclass, const char *name, size_t extrabytes);

//Destroys a class and its associated class
void Objc_disposeclasspair (class CLS);

//Register the class created by Objc_allocateclasspair
void Objc_registerclasspair (class CLS) in the application;

Objc_allocateclasspair function: If we want to create a root class, then superclass is specified as nil. Extrabytes is typically specified as 0, which is the number of bytes assigned to the index ivars of the end of the class and class object.

In order to create a new class, we need to invoke Objc_allocateclasspair. You then use functions such as Class_addmethod,class_addivar to add methods, instance variables, and properties to the newly created class. Once this is done, we need to call the Objc_registerclasspair function to register the class, and the new class can then be used in the program.

Instance methods and instance variables should be added to the class itself, and class methods should be added to the class's meta class.

The Objc_disposeclasspair function is used to destroy a class, but it should be noted that if there are instances of classes or subclasses of the program running, you cannot call the method on the class.

When we introduced the Meta class, we already had access to these functions, and here's an example to see how these functions are used.

The code is as follows Copy Code
Class cls = Objc_allocateclasspair (Myclass.class, "MySubClass", 0);
Class_addmethod (CLS, @selector (SUBMETHOD1), (IMP) imp_submethod1, "v@:");
Class_replacemethod (CLS, @selector (METHOD1), (IMP) imp_submethod1, "v@:");
Class_addivar (CLS, "_ivar1", sizeof (NSString *), log (sizeof (NSString *)), "I");

objc_property_attribute_t type = {"T", "@" NSString ""};
objc_property_attribute_t ownership = {"C", ""};
objc_property_attribute_t Backingivar = {"V", "_ivar1"};
objc_property_attribute_t attrs[] = {type, ownership, Backingivar};

Class_addproperty (CLS, "Property2", Attrs, 3);
Objc_registerclasspair (CLS);

id instance = [[CLS alloc] init];
[Instance Performselector: @selector (SUBMETHOD1)];
[Instance Performselector: @selector (method1)];


The output of the program is as follows:

The code is as follows Copy Code
2014-10-23 11:35:31.006 runtimetest[3800:66152] Run Sub Method 1
2014-10-23 11:35:31.006 runtimetest[3800:66152] Run Sub Method 1

Creating objects Dynamically

The function of dynamically creating an object is as follows:

The code is as follows Copy Code
To create a class instance
ID Class_createinstance (class cls, size_t extrabytes);

To create a class instance at the specified location
ID objc_constructinstance (Class cls, void *bytes);

Destroying class instances
void * objc_destructinstance (id obj);


class_createinstance function: When an instance is created, memory is allocated to the class in the default memory area. The Extrabytes parameter represents the number of extra bytes allocated. These additional bytes can be used to store instance variables outside of the instance variables defined in the class definition. This function is not available in the ARC environment.

The effect of calling Class_createinstance is similar to the +alloc method. But when using class_createinstance, we need to know exactly what we're going to do with it. In the following example, we use NSString to test the actual effect of the function:

  code is as follows copy code
id theobject = Class_createinstance (nsstring.class, sizeof (unsigned));
ID str1 = [theobject init];

NSLog (@ "%@", [str1 class]);

ID str2 = [[NSString alloc] initwithstring:@ "test"];
NSLog (@ "%@", [str2 class]);


The output results are:

2014-10-23 12:46:50.781 runtimetest[4039:89088] NSString
2014-10-23 12:46:50.781 runtimetest[4039:89088] __nscfconstantstring

As you can see, using the Class_createinstance function to get the NSString instance instead of the default placeholder class __nscfconstantstring in the class cluster.

Objc_constructinstance function: Creates a class instance at the specified location (bytes).

Objc_destructinstance function: Destroys an instance of a class, but does not release and remove any references associated with it.

Instance action function

An instance action function is primarily a series of operational functions for the instance object we create, and we can use this set of functions to get some of the information we want from the instance object, such as the value of the variable in the instance object. This set of functions can be grouped into three small categories:

1. Functions that operate on an entire object, such functions include

The code is as follows Copy Code
Returns a copy of the specified object
ID object_copy (ID obj, size_t size);

Frees the memory occupied by a specified object
ID object_dispose (id obj);

There is a scenario where we have Class A and Class B, and Class B is a subclass of Class A. Class B extends Class A by adding some additional attributes. Now we have created an instance object of Class A, and want to convert this object to an instance object of Class B at run time, so that you can add data to the properties of Class B. In this case, we have no way to convert directly, because instances of Class B are larger than instances of Class A, and there is not enough space to place objects. At this point, we're going to use the above functions to handle this situation, as shown in the following code:

The code is as follows Copy Code
NSObject *a = [[NSObject alloc] init];
ID newb = Object_copy (A, class_getinstancesize (Myclass.class));
Object_setclass (Newb, Myclass.class);
Object_dispose (a);


2. Functions that operate on object instance variables, which include:

  code is as follows copy code
//Modify the value of an instance variable of a class instance
Ivar object_setinstancevariable (id obj, const char *name, void *value);

//Gets the value of the object instance variable
Ivar object_getinstancevariable (id obj, const char *name, void **outvalue);

//Returns a pointer to any additional bytes allocated by the given object
void * object_getindexedivars (id obj);

//Returns the value of the instance variable in the object
ID object_getivar (id obj, Ivar Ivar);

//Set the value of the instance variable in the object
void Object_setivar (id obj, Ivar Ivar, id value);


If the Ivar of the instance variable is already known, then the call to Object_getivar will be faster than the Object_getinstancevariable function, and in the same case the Object_setivar is better than the object_ Setinstancevariable fast.

3. A function that operates on a class of objects that contains:

The code is as follows Copy Code
Returns the class name of the given object
const char * object_getclassname (id obj);

Returns the class of the object
Class object_getclass (id obj);

Set the class of an object
Class Object_setclass (Id obj, Class cls);


Get class definition

The objective-c dynamic runtime automatically registers all of the classes defined in our code. We can also create class definitions at run time and register them using the Objc_addclass function. Runtime provides a series of functions to get information about class definitions, which include:

The code is as follows Copy Code
Gets a list of registered class definitions
int Objc_getclasslist (Class *buffer, int buffercount);

Creates and returns a list of pointers to all registered classes
Class * objc_copyclasslist (unsigned int *outcount);

Returns the class definition for the specified class
Class objc_lookupclass (const char *name);
Class objc_getclass (const char *name);
Class objc_getrequiredclass (const char *name);

Returns the meta class of the specified class
Class objc_getmetaclass (const char *name);


Objc_getclasslist function: Gets the list of registered class definitions. We cannot assume that the class object obtained from the function inherits from the NSObject system, so calling the method on these classes should first detect whether the method is implemented in this class.

The following code demonstrates the use of this function:

The code is as follows Copy Code
int numclasses;
Class * classes = NULL;

numclasses = objc_getclasslist (NULL, 0);
if (numclasses > 0) {
Classes = malloc (sizeof (Class) * numclasses);
Numclasses = Objc_getclasslist (classes, numclasses);

NSLog (@ "Number of classes:%d", numclasses);

for (int i = 0; i < numclasses; i++) {

Class cls = Classes[i];
NSLog (@ "Class name:%s", Class_getname (CLS));
}

Free (classes);
}




The output results are as follows:





2014-10-23 16:20:52.589 runtimetest[8437:188589] Number of classes:1282


2014-10-23 16:20:52.589 runtimetest[8437:188589] class Name:ddtokenregexp


2014-10-23 16:20:52.590 runtimetest[8437:188589] class name: _nsmostcommonkoreancharskeyset


2014-10-23 16:20:52.590 runtimetest[8437:188589] class Name:os_xpc_dictionary


2014-10-23 16:20:52.590 runtimetest[8437:188589] class Name:nsfilecoordinator


2014-10-23 16:20:52.590 runtimetest[8437:188589] class Name:nsassertionhandler


2014-10-23 16:20:52.590 runtimetest[8437:188589] class Name:pfubiquitytransactionlogmigrator


2014-10-23 16:20:52.591 runtimetest[8437:188589] class Name:nsnotification


2014-10-23 16:20:52.591 runtimetest[8437:188589] class Name:nskeyvaluenilsetenumerator


2014-10-23 16:20:52.591 runtimetest[8437:188589] class Name:os_tcp_connection_tls_session


2014-10-23 16:20:52.591 runtimetest[8437:188589] class name: _pfroutines


...... And a lot of output.





There are three methods for getting the class definition: Objc_lookupclass, Objc_getclass, and Objc_getrequiredclass. If the class is not registered at run time, Objc_lookupclass returns nil, and Objc_getclass invokes the class to process the callback and confirms that the class is registered again, and then returns nil if the confirmation is not registered. The Objc_getrequiredclass function operates in the same way as Objc_getclass, except that if a class is not found, it kills the process.





Objc_getmetaclass function: If the specified class is not registered, the function invokes the class to process the callback, confirms that the class is registered, and returns nil if the confirmation is not registered. However, each class definition must have a valid class definition, so this function always returns a meta class definition, regardless of whether it is valid or not.

Summary

In this chapter, we introduce the data structure related to class and object in the runtime runtime, and through these data functions, we can have a glimpse of some information of objective-c object-oriented implementation. In addition, this data can be manipulated flexibly through rich operation functions.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.