iOS development: detailed objective-c RunTime

Source: Internet
Author: User

objective-c the whole runtime thing. (a) message mechanismrecently looking for a job, objective-c in the runtime is often asked a question, almost is the interview big company must ask a question. There are, of course, some other questions that are almost certainly asked, such as Runloop,block, memory management, and so on. Other questions I will introduce in other articles if I have the opportunity. This article mainly introduces the runtime.

runtime abbreviation. is the system at the time of the operation of some mechanism , the most important is the message mechanism . For the C language, the function's call will decide which function to call at compile time (see here for the C-language function call). The sequence executes directly after compilation, without any ambiguity.

The function call of OC becomes a message sent. belongs to the dynamic call thread. It is not possible at compile time to decide which function to actually call (it turns out that OC can call any function during the compile phase, even if the function is not implemented, as long as it is declared without an error.) C language will be in the compilation phase error). The corresponding function will be called based on the name of the function only when it is actually running.

How does OC implement dynamic invocation? Let's take a look at how OC achieves the secret of dynamic calls by sending messages. If you write such a code in OC:

1 [obj makeText];

Where obj is an object and Maketext is a function name. For such a simple invocation. Runtime at compile time will convert the above code into

1 objc_msgSend(obj,@selector(makeText));

First, let's take a look at the Obj object, which is inherited from NSObject in iOS.

1 2 3 @interface NSObject <NSOBJECT> {     Class isa  OBJC_ISA_AVAILABILITY; }

There is a class Isa pointer in the NSOBJCET. Then we look at class:

1 2 3 4 5 6 7 8 9 Ten One A - - typedef struct objc_class *Class; struct objc_class {   Class isa; // 指向metaclass       Class super_class ; // 指向其父类   const char *name ; // 类名   long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取   long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;   long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量);   struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址   struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;   struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率;   struct objc_protocol_list *protocols; // 存储该类遵守的协议     }

As we can see, there are a lot of things in a class, and here's a one by one explanation:

Class Isa: Point to Metaclass, which is the static class. In general, ISA in an Obj object points to the normal class, which stores ordinary member variables and object methods (the "-" method at the beginning of the "-"), the ISA pointer in the normal class to the static class, and the static class that stores statically type member variables and class methods (" + "starts with the method).

Class Super_class: Points to the parent class, or null if the class is a root class.

The following picture is a good description of the inheritance relationship of classes and objects:

Note : All metaclass in the ISA pointer are pointed to the metaclass. And the metaclass point to itself. Root Metaclass is generated by inheriting the root class. is consistent with the root class struct member, which is the structure mentioned earlier. The difference is that the ISA pointer to root metaclass points to itself.

The rest of the class is not explained here, so let's take a look at the following:

@selector (Maketext): This is an Sel method selector. The main function of SEL is to quickly find the corresponding method's function pointer by means of the method name (Maketext), and then call its function. The SEL itself is an address of type int, with the name of the method stored in the address. For a class. Each method corresponds to an sel. So there cannot be 2 identical methods in the iOS class, even if the parameter types are different because the SEL is generated from the method name, the same method name can only correspond to one sel.

Let's take a look at how the specific message is sent after it's been dynamically searched for the corresponding method.

First, the compiler converts the code [obj Maketext] into objc_msgsend (obj, @selector (Maketext)), in the Objc_msgsend function. The class of obj is first found through the ISA pointer of obj. In class, first go to the cache through the SEL to find the corresponding function method (guess the Cache method list is the SEL key through the hash table to store, this can improve the function lookup speed), if not found in the cache. Again to find in the methodlist, if not found in MethodList, then take superclass to find. If found, the method is added to the cache to facilitate the next lookup, and the function pointer in method jumps to the corresponding function to execute.

    iOS Development: detailed OBJECTIVE-C Runtime What is objective-c runtime?

Objective-c Runtime is a C library that implements the Objective-c language . objects can be represented in the structure of the C language, whereas methods (methods) can be implemented with C functions. Once these structures and functions are encapsulated by the runtime function , OBJECTIVE-C programmers can create, inspect, modify classes, objects, and their methods while the program is running.

In addition to encapsulation, the OBJECTIVE-C Runtime Library is also responsible for locating the final execution code of the method. When the program executes [object DoSomething], the method is not directly found and called. Instead, a message is sent to the object (here, we usually call it the recipient). The runtime library gives a chance for the object to decide what response to make based on the message. Alan Kay repeatedly emphasized that message passing (message-passing) is the most important part of Smalltalk (Objective-c based on Smalltalk), not the object:

I am very sorry that I have created the word "object" before on this topic, and many people are now flocking to this concept.

In fact, the more important idea here is "message command" (messaging), which is the core content of Smalltalk (there are still some content not yet complete). A short word in Japanese is called "Ma", which is used to denote something between two objects, and the word closest to it in English may be "interstitial". The key to building a large and scalable system is to design the way it communicates between its modules, rather than focusing on its internal properties and behavior.

In fact, in an article that introduces Smalltalk virtual machines, this programming technique is called message delivery or messaging paradigm. "Object-oriented" is often used to describe memory management systems.

The word OBJC runtime is used in speeches and articles, and it appears to be only one, in fact there are many runtime libraries. Although they all support object introspection and message reception, they have different features and implementations (for example, the same message is sent, Apple's runtime is done in one step, and the GNU runtime queries the messages and then executes the found function in two steps). All of the following discussions are based on Apple's latest runtime library (the version of Apple at OSX 10.5 and iOS).

In that speech, I decided to study the functions of some areas of the runtime library. I found something that I wanted to get to know better, and then made it into a question-and-answer form to make my speech.

Dynamically creating classes

How to implement Key-value observing?

When I was preparing this speech, an article called KVO considered harmful began to have a lot of fans. It raises a lot of correct criticisms of KVO, but rather than abandoning the observer pattern, I would like to explore a new way of achieving it.

KVO the key to implementing the observer pattern is that it surreptitiously changes the class of the object being observed, and after it subclasses the original class, it is able to customize the method of the object to invoke the callback method of KVO. This is done through objc_duplicateclass, but unfortunately, this method is not public and we cannot invoke it privately.

All roads lead to Rome, but in addition to Objc_duplicateclass, there are other ways to implement observer patterns by using secret subclasses, such as creating and registering "class pair." So what is class pair? For objective-c classes, there is a pair of class objects to define it: Class object defines an instance method of this class, and Metaclass defines the classes method of this class. So each class is actually a single case of its metaclass.

This code shows how the Observer pattern works. When you add an observer to an object, the object first checks to see if it can be observed, and if it does, it will create a new class, replace the method of the original class with our own-dealloc, as well as the-class method, similar to the Kvo object, when you access the class name of the object being observed, It returns the original class name, not the newly generated class.

After the class is created, we need to add a setter method to the property according to Key-value coding: This setter method takes the value before the property modification and the modified value, and then calls the block form of the callback function, and tells the Observer the two values. The block can be called asynchronously, according to our wishes.

Note that-addobserverforkey:withblock: Uses S object_setclass () to replace the class of the observed object with the newly formed class. The main purpose of this is to change the way the message is transformed into a method, but it takes great care that the original class and the new class must have the same member variable layout. Because member variables are also accessed with runtime, modifying the class of an object may cause the runtime to not find the corresponding variable.

We were having trouble storing the observers ' collections because there was no place to save them. Adding member variables to the Observerpattern class does not work because there is no object that generates this class at all. The member variable of the observed object is its original class, and it does not consider these observers.

OBJECTIVE-C runtime helped us get out of this dilemma by introducing associated objects . In runtime, in theory, all objects can have dictionaries that contain other objects. By associated references, the observed objects can store and access their observers without the need for additional member variables.

If you run multiple times, you will find that Observerpattern is still a bit of a glitch. Because the observer callback is called asynchronously, the Observer

The changed events received are also chaotic. This means that the observer cannot actually distinguish what the final state of the observed attribute is, and the new value in the callback may have been modified already. I'm doing this to illustrate that calling callbacks synchronously in KVO is actually a useful feature, not a bug.

Creating objects

What are those extra bytes for?

When you create a Objective-c object, runtime allocates a little extra space after the instance variable storage area. What is the purpose of this? You can get the space start pointer (with Object_getindexedivars), and then you can index the instance variable (ivars). Well, I'll use a custom array to illustrate the usefulness of index Ivars.

Let's create an array! Two things can be seen from this simplearray: the most obvious is that it uses the cluster pattern. When using the +alloc method to return an object, the object is normally allocated with all memory, but in this case, the +alloc does not know how much memory is needed. Only if-initwithobjects:count is called: After that, it is possible to calculate how much memory this array needs based on the number of objects in the array, so +alloc simply returns a placeholder, and the real array object is assigned and returned only after initialization.

Maybe you ask why we use clusters to make things so complicated, use calloc () to allocate a chunk of the appropriate cache, and then put those object pointers inside. The answer is that you want to use the locality principle to improve access performance. From the design of arrays we can see that each time an array pointer is accessed, there is a great chance of accessing the cache pointer, so putting them side-by in memory means finding one of them is finding another.

Message distribution

How do messages be forwarded?

Objective-c one of the powerful features is that an object does not need to implement a method, although it declares the selector (selector) at compile time. But it can then determine the method implementation at run time, or forward these messages to other objects, or make exceptions, or do something else. But some aspects of this feature have been bothering me: message forwarding (msg forwarding) calls-forwardinvocation: And then passes in a Nsinvocation object. But this nsinvocation class is defined in the Foundation library, does it mean that runtime work requires foundation coordination?

I try to dig into the reason and find out that the answer is not what I think, runtime doesn't need to know foundation. Runtime will have the program define the forwarding function (forwarding functions), and when objc_msgsend () cannot find the implementation of the selector, that forwarding function is called. As soon as the program starts, Corefoundation will-forwardinvocation: defined as a forwarding function.

Let's create a ruby! Of course it's not true. Ruby,ruby has a function called #method_missing, and when the object receives a message that it does not implement, the function is transferred, which is similar to Smalltalk's practice. Using Objc_setforwardhandler, we can also implement Ruby-like methodmissing in Objective-c classes: methods.

Summarize

OBJECTIVE-C runtime can effectively help us to add a lot of dynamic behavior to the program. Some developers, in addition to using method swizzling to help debug the program, do not use it in the actual program, but runtime programming does have a lot of features, which should be an important tool for practical application code writing.

Original address: HTTP://BL

iOS development: detailed objective-c RunTime

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.