IOS Runtime detailed

Source: Internet
Author: User
Tags set set

Note: This article was transferred from: http://www.jianshu.com/p/adf0d566c887

first, the introduction of the run-time

Objective-c language is a dynamic language that puts a lot of static language in the process of compiling and linking time to the runtime.
For Objective-c, the runtime system is like an operating system: it allows all the work to run properly. The runtime is basically written in C and sink, which makes the C language have object-oriented capabilities.
In runtime, objects can be represented in the structure of the C language, and methods can be implemented with C functions, plus some additional features. These structures and functions are encapsulated by the runtime function, making OC's object-oriented programming possible.
Find out the final execution code of the method: when the program executes [object DoSomething], a message (dosomething) is sent to the message Receiver (object), and the runtime responds differently depending on whether the message receiver can respond to the message.

Ii. Class and object-based data structure

The Objective-c class is represented by the class type, which is actually a reference to the
Pointer to the Objc_class struct.


struct object_class *Class

It is defined as follows:
See the definition of objc_class struct in objc/runtime.h as follows:

struct object_class{class Isa objc_isa_availability;#If!__objc2__ Class super_class objc2_unavailable;Parent classConstChar *name objc2_unavailable;Class namelong version objc2_unavailable; //The version information of the class, the default is 0 long info objc2_unavailable; //class information for some bits identified 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; //method definition of the linked list struct objc_cache *cache objc2_unavailable; //method Cache struct objc_protocol_list *protocols objc2_unavailable; //protocol list #endif}objc2_unavailable;   

Describe its execution process:
Nsarray *array = [[Nsarray alloc] init];

Objc_object

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

struct objc_object{     Class isa OBJC_ISA_AVAILABILITY;};typedef struct objc_object *id;

As you can see, the struct has only one font, the ISA pointer to its class. This
When we send a message to a Objective-c object, the runtime library is based on the
The instance object's Isa pointer finds the class to which this instance object belongs. The runtime library will be in the class
List of methods and methods in the parent class to find the selector that corresponds to the message.
method to run this method after finding it.

Meta classes (META Class)

Meta-class is a class of class objects.
As we mentioned above, all classes are themselves an object, and we can send a message to this object (that is, call the class method).
Since it is an object, it is also a objc_object pointer, which contains an Isa pointer to its class. So what does this ISA pointer point to?

To invoke a class 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, which stores all class methods of a class in Meta-class.

So, the ISA pointer to the class object that invokes the class method is pointing to the Meta-class
When we send a message to an object, runtime looks for the method in the list of methods of the class to which the object belongs, and when a message is sent to a class, it is found in the Meta-class method list of the class.

Further down, Meta-class is also a class, can also send a message to it, then its Isa point to what? To keep this structure from extending indefinitely, Objective-c's designers let all Meta-class Isa point to the meta-class of the base class as their owning class.

That is, any meta-class under the NSObject inheritance system uses NSObject's Meta-class as its own class, while the base class's Meta-class Isa pointer is pointing to itself.

Through the above description, coupled with the analysis of the Super_class pointer in the OBJC_CLASS structure, we can describe a class and the corresponding Meta-class class of an inheritance system, the following code


Snip20160501_1.pngcategory

The category is a pointer to a struct that points to the classification, which is defined as follows:

typedefstructObjc_category *categorystruct objc_category{char *category_name objc2_unavailable; //category name char *class_name objc2_unavailable; //category belongs to class name struct OBJC _method_list *instance_methods objc2_unavailable; //instance method list struct objc_method_list *class_methods objc2_unavailable; //class method list struct objc_protocol_list *protocols objc2_unavailable; //classification}            

This structure mainly contains the instance and class methods of the classification definition, where the Instance_methods list is a subset of the method list in Objc_class, and the Class_methods list is a subset of the meta-class method list.
It can be found that there is no Ivar member variable pointer in the category, which means that instance variables and attributes cannot be added to the category:

struct objc_ivar_list *ivars             OBJC2_UNAVAILABLE;  // 该类的成员变量链表
third, runtime associated objects

Let's take a look at the correlation API, which is very simple to use with only these three APIs:

1. Setting Association values

Parameter description:
Object: Who is associated with, usually self-transmitting
Key: A unique key, obtained by the key when the value is obtained, usually using the static
const void * To declare
Value: The values set by the association
Policy: Memory management policies, such as using copy

void objc_setAssociatedObject(id object, const void *key, id value, objc _AssociationPolicy policy)
2. Get the associated value

Parameter description:
Object: Who is associated with, usually self, the object that is associated with the object specified when the association is set
Key: Unique key, the key that is specified when the association is set

id objc_getAssociatedObject(id object, const void *key)
3. Cancel the Association
void objc_removeAssociatedObjects(id object)
Association policy

Usage scenarios:
You can add properties to a category

0,             // 表示弱引用关联,通常是基本数据类型OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,   // 表示强引用关联对象,是线程安全的OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 表示关联对象copy,是线程安全的OBJC_ASSOCIATION_RETAIN = 01401, // 表示强引用关联对象,不是线程安全的OBJC_ASSOCIATION_COPY = 01403 // 表示关联对象copy,不是线程安全的};
Iv. methods and messages1. SEL

The SEL, also called the selector, is a pointer to the selector that represents a method, which is defined as follows:

typedef struct objc_selector *SEL;

The selector method is used to represent the name of the run-time method. Objective-c at compile time, a unique integer identifier (an int type address) is generated based on the name and parameter sequence of each method, which is the SEL.
Two classes, as long as the method name is the same, then the method of the SEL is the same, each method corresponds to a sel. So in objective-c the same class (and class inheritance system), there cannot be 2 methods with the same name, even if the parameter types are different
If you define the following two methods in a class: Error

- (void)setWidth:(int)width;- (void)setWidth:(double)width;

Of course, different classes can have the same selector, which is fine. When instance objects of different classes perform the same selector, they will find their corresponding imp in the respective list of methods according to selector.
All the SEL in the project consists of a set set, and if we think of a method in the collection of this method, we just need to find the corresponding sel of the method, and the SEL is actually a hash of the string based on the method name, And for the comparison of strings only need to compare their address on it, can be said that the speed of no language incomparable!
In essence, the SEL is just a pointer to a method (to be exact, a key value that is hashed based on the method name, which uniquely represents a method), and it exists only to speed up the query of the method.
The SEL can be obtained in the following three ways:
A, Sel_registername function
B, objective-c compiler-supplied @selector ()
C, Nsselectorfromstring () method

2. IMP

The imp is actually a function pointer that points to the address of the method implementation.
It is defined as follows:

id (*IMP)(id, SEL,...)

The first argument is a pointer to self (the memory address of the class instance if it is an instance method, or a pointer to a meta-class if it is a class method)
Second parameter: is the method selector (selector)
Next parameter: The parameter list of the method.

The SEL described earlier is to find the final implementation of the method imp. Since each method corresponds to a unique sel, we can quickly and accurately obtain the imp corresponding to it using the SEL, and the lookup process will be discussed below. When we get the imp, we have the entry point to execute this method code, so we can use the function pointer just like the normal C language function.

3. Method

method is used to represent methods in a class definition, it is defined as follows:

typedef struct objc_method *Methodstruct objc_method{ SEL method_name OBJC2_UNAVAILABLE; // 方法名 char *method_types OBJC2_UNAVAILABLE; IMP method_imp OBJC2_UNAVAILABLE; // 方法实现}

We can see that the struct contains a SEL and imp, which is actually a mapping between the SEL and the Imp. With SEL, we can find the corresponding IMP, thus invoking the implementation code of the method.

4. Method invocation Process
Snip20160501_2.png


In Objective-c, the message is not bound to the method implementation until run time. The compiler translates the message expression [receiver message] into a call to a message function, which is objc_msgsend. This function takes the message receiver and the method name as its underlying parameters, as shown in the following

objc_msgSend(receiver, selector)

If there are other parameters in the message, the form of the method is as follows:

objc_msgSend(receiver, selector, arg1, arg2,...)

This function completes all the things that are bound dynamically:

A, first it finds the selector corresponding method realization. Because the same method can
Can have different implementations in different classes, so we need to rely on the recipient's class
To find the exact implementation.
B, invoke the method implementation, and pass all the parameters of the receiver object and method to it.
C, finally, it will implement the returned value as its own return value.

The key to the message is the struct objc_class we discussed in the previous section, which has two fields that we are interested in distributing the message:
Pointer to parent class
The method of a class is divided into a publication, namely methodlists.
When we create a new object, we first allocate memory for it and initialize its member variables. Where the ISA pointer is also initialized, allowing the object to access the class and class inheritance system.

Demonstrates the basic framework for such a message:
When a message is sent to an object, it is first looked up from the method used by the runtime system cache.
If found, execute the method, if not found, proceed with the following steps

Objc_msgsend gets the structure of the class through the object's Isa pointer, and then finds the selector of the method in the method sub-publication.
If a pointer to the parent class in the selector,objc_msgsend struct is not found, find its parent class and find the selector of the method in the sub-publication of the parent class.
In this way, the NSObject class will be reached along the inheritance system of the class. Once positioned to selector, the function acquires the implementation entry point, passes in the corresponding parameter to execute the method's implementation, and adds the method into the cache if it is not finally positioned to selector, then the message forwarding process, which we discuss later.

5. Message forwarding

When an object can receive a message, it goes through the normal method invocation process. But what happens if an object cannot receive the specified message? By default, if the method is invoked as an [object message], the compiler will error if object cannot respond to message messages. But if it's a perform ... , you need to wait until the runtime to determine if object can receive a message. If not, the program crashes.


Snip20160501_3.png


In general, when we are not sure whether an object can receive a message, Respondstoselector is called first: to judge. As shown in the following code:

if([self respondsToSelector:@selector(method)]){      [self performSelector:@selector(method)];}

However, we would like to discuss the situation of not using respondstoselector: judgment. This is the focus of our section.

When an object is unable to receive a message, it initiates the so-called "message forwarding" mechanism, through which we can tell the object how to handle an unknown message. By default, the object receives an unknown message that causes the program to crash, and through the console we can see the following exception information:

This exception message is actually thrown by NSObject's "Doesnotrecognizeselector" method. However, there are some steps we can take to get our program to execute specific logic and avoid a program crash.

The message forwarding mechanism is basically divided into three steps:

1>, dynamic method analysis
2>, Standby Receiver
3>, full forwarding
Forwarding Flowchart for messages:


Snip20160501_5.png Dynamic Method Analysis

When an object receives an unknown message, it first calls the class method of the owning class
+resolveinstancemethod: (instance method) or
+resolveclassmethod: (class method).

In this method, we have the opportunity to add a "processing method" to the unknown message, which can be dynamically added to the class by the runtime Class_addmethod function.

This scenario is more about implementing the @dynamic attribute.

Alternate recipient
(id)forwardingTargetForSelector:(SEL)aSelector

If the message cannot be processed in the previous step, runtime continues to tune the following methods:
If an object implements this method and returns a non-nil result, the object will be the new recipient of the message, and the message will be distributed to the object. Of course, this object cannot be self itself, otherwise there is an infinite loop. Of course, if we don't specify the appropriate object to handle aselector, we should call the implementation of the parent class to return the result.

This step is appropriate for us to forward the message to another object that can handle the message. However, this step cannot process the message, such as the parameters and return values of the action message.

Full message forwarding

If the unknown message cannot be processed in the previous step, the only thing that can be done is to enable the full message forwarding mechanism.
We'll first pass, specify the method signature, and if nil is returned, it means no processing.
The following code:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{   if ([NSStringFromSelector(aSelector) isEqualToString:@"testInstanceMethod"]){     return [NSMethodSignature signatureWithObjcTypes:"[email protected]:"]; } return [super methodSignatureForSelector: aSelector];}

If the method signature is returned, the following method is called in to the next step, and the object creates a Nsinvocation object that represents the message, encapsulating all the details related to the unhandled message in Aninvocation, including selector, target, and parameters.
We can choose to forward the message to other objects in the Forwardinvocation method. We can do a lot of processing by Aninvocation objects, such as modifying the implementation method, modifying the response object and so on.
As shown below:

- (void)forwardInvovation:(NSInvocation)anInvocation{    [anInvocation invokeWithTarget:_helper];    [anInvocation setSelector:@selector(run)]; [anInvocation invokeWithTarget:self];}
Five, Method swizzling1.Swizzling principle

Calling a method in Objective-c is actually sending a message to an object, and the only way to find the message is by selector's name. Therefore, we can use Objective-c's runtime mechanism to realize the implementation of the corresponding method of exchanging selector at runtime to achieve our goal.

Each class has a list of methods that hold the mapping of selector's name and method implementation. IMP is a bit like a function pointer, pointing to a concrete method implementation

Let's take a look at the diagram between SEL and imp:


Snip20160501_6.png


As can be seen, each SEL corresponds to an imp one by one, under normal circumstances through the SEL can find the corresponding message of the IMP implementation.

But now all we have to do is untie the link and connect it to the imp of our custom function. Of course, the exchange of two SEL imp, or can be exchanged back again. After the exchange has become such as


Snip20160501_7.png


As can be seen, we use the swizzling feature, Selectorc method implementation IMPC and Selectorn method implementation IMPN Exchange, when we call Selectorc, that is, to send the object SELECTORC message, The corresponding method found in the search is IMPN rather than IMPC.

IOS Runtime detailed

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.