Several Frequently Asked Questions about iOS ----- RunTime

Source: Internet
Author: User

Several Frequently Asked Questions about iOS ----- RunTime

Speaking of RunTime, this is another pain point. How much interest is there to learn about iOS development? Then, we will study OC for the sake of interest. After all, I bought an iPhone, a MacBook, and a developer account in college. (If xCode7 was used to test a real machine, I needed a developer account )? So I suggest the interviewers here, don't ask you how to study iOS development in college .... Because most of them are brought out by someone like me. If you learn Java on your own and don't understand it, you can ask the teacher at school. Who are you going to ask for iOS? The most important thing is that iOS has been on fire for 12 years... You have been working for 12 years, and there is no tutorial in China... It's really good to have 3 programmers who can learn and think about the Runtime point ..... Therefore, it is not necessary to ask this individual .... In addition, the first batch of iOS developers started iOS development only after their development experience in year 45. What do you think? Which of the following is really rare .... Okay, it's over .... Starting point ------ Runtime

RunTime

Literally, it is "Runtime". A little professional is the state of the program at Runtime (here I will talk about Runtime as a professional knowledge of the OC language, it is not a professional knowledge of iOS development, and Java also has a Runtime ).

1. Dynamic vs static Language

OC is the language used for running, which means it will try its best to delay the logic to be executed during compilation and linking to the runtime. This gives programmers great flexibility. programmers can direct messages to appropriate objects as needed, you can even use an exchange method (calling an object method in OC can be seen as sending messages to an object ). This requires the use of runtime, which can be used for object introspection to view what they are doing and what they cannot do, and suitable for sending messages: if you are interested, you can view the NSObject class-forwardingTargetForSelector: And-forwardInvocation: methods. P.S. Not the NSObject protocol! ). If we compare it with a language like C. In C, you write from the main () method and then write the logic from top to bottom and execute the program in the order you write the code. A c struct cannot forward function execution requests to other targets (other targets ). Probably your program is like this:

 

 
 
int main(int argc, const char **argv[]){            printf("Hello World!");    return 0;}
The compiler parses, optimizes, and then converts the optimized code into a compilation: 
.text .align 4,0x90 .globl _main_main:Leh_func_begin1: pushq %rbpLlabel1: movq %rsp, %rbpLlabel2: subq $16, %rspLlabel3: movq %rsi, %rax movl %edi, %ecx  movl %ecx, -8(%rbp) movq %rax, -16(%rbp)  xorb %al, %al  leaq LC(%rip), %rcx  movq %rcx, %rdi  call _printf  movl $0, -4(%rbp)  movl -4(%rbp), %eax  addq $16, %rsp  popq %rbp  retLeh_func_end1:  .cstringLC:  .asciz "Hello World!"
The process of linking the database and generating executable programs is similar to that of OC. The generated code depends on whether the OC Runtime Library exists. When learning OC, the first thing we know (the simplest one) is the code wrapped in parentheses in OC...
[self doSomethingWithVar:var1];
Then:
objc_msgSend(self,@selector(doSomethingWithVar:),var1);
After that... I can't find what it is ....

Ii. What is OC Runtime?

The Runtime of OC is a Runtime Library, which is mainly written in C and sink. It adds the facial object capabilities to C and creates OC. This means that it is loaded in Class information to distribute all methods, forward methods, and so on. The OC runtime creates all required struct to make it possible to program the interface objects of the OC.

Iii. OC Runtime terminology

Before going deeper, let's first understand some terms. Mac and iPhone developers are concerned with two runtimes: Modern runtime (Modern Runtime) and Legacy Runtime (outdated Runtime ). Modern Runtime: covers all 64-bit Mac OS x applications and all iPhone OS applications. Legacy Runtime: covers all other applications (all 32-bit Mac OS X applications). There are two basic types of methods. Instance Method: starts with '-', such as-(void) doFoo. Class Method (Class Method): starts with '+', for example, + (id) alloc. Methods are similar to C functions. They are a set of code that executes a small task, such:

 
- (NSString *)movieTitle { return @"Futurama: Into the Wild Green Yonder"; }
Selector in Objective-C, selector is only a data structure of C, used to represent an OC method you want to execute on an object. The definition in runtime is like this... 

typedef struct objc_selector  *SEL;
Use it like this...
SEL aSel = @selector(movieTitle);
Message)
[target getMovieTitleForObject:obj];
The message is the part of the square brackets '[]', and the object (target) to which you want to send the message. The method you want to execute above) and the parameters (arguments) you sent. OC messages are different from C function calls. In fact, sending a message to an object does not mean that it will execute it. The Object checks the message sender. Based on this, it determines whether to execute a different method or forward the message to another target Object. Class if you view the runtime information of a Class, you will see this...
typedef struct objc_class *Class;typedef struct objc_object {    Class isa;} *id;
Here are a few things. We have an OC class struct and an object struct. Objc_object has only one isa pointer to the class, which is the term "isa pointer" (isa pointer ). This isa pointer is used when you send a message to an object, OC Runtime checks an object and its class and starts to check whether it responds to everything these selectors need. Finally, I saw the id pointer. By default, id pointers are not used unless they are OC objects. When you have an id pointer, you can then ask the class of the object to see if it responds to a method, and so on, then you can execute more operations after you know what the Pointer Points. You can see in the Block in the LLVM/Clang document
struct Block_literal_1 {    void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock        int flags;        int reserved;         void (*invoke)(void *, ...);     struct Block_descriptor_1 {         unsigned long int reserved; // NULL             unsigned long int size;  // sizeof(struct Block_literal_1)        // optional helper functions             void (*copy_helper)(void *dst, void *src);        void (*dispose_helper)(void *src);         } *descriptor;        // imported variables};
Blocks is designed to be OC-compatible runtime, so they are treated as objects, so they can respond to messages, such as-retain,-release,-copy, and so on.

IMP (Method Implementations)

typedef id (*IMP)(id self,SEL _cmd,...);
IMP is a function pointer to method implementation, which is generated by the compiler for you. If you are new to OC, you do not need to contact them directly now, but we will see how OC runtime will call your method. OC Classes (OC class), so what is OC class? A class implementation in OC looks like this:
 
@interface MyClass : NSObject { // vars NSInteger counter; } // methods -(void)doFoo; @end

However, runtime does not only need to trace these
#if !__OBJC2__       Class super_class                        OBJC2_UNAVAILABLE;    const char *name                         OBJC2_UNAVAILABLE;    long version                             OBJC2_UNAVAILABLE;    long info                                OBJC2_UNAVAILABLE;    long instance_size                       OBJC2_UNAVAILABLE;        struct objc_ivar_list *ivars             OBJC2_UNAVAILABLE;        struct objc_method_list **methodLists    OBJC2_UNAVAILABLE;        struct objc_cache *cache                 OBJC2_UNAVAILABLE;        struct objc_protocol_*protocols          OBJC2_UNAVAILABLE;#endif

We can see that a class has its parent class reference, its name, instance variable, method, cache, and the Protocol it complies. Runtime requires this information when responding to class or instance methods.

4. Does the Class define the object or the object itself? How it is implemented (Note: The reader needs to distinguish between Class and class, just as Nil and nil are used differently)

Yes, as I said before, the OC class is also an object, and runtime processes this by creating Meta Classes. When you send a message like [NSObject alloc], you are sending a message to the class Object. This class object must be an instance of MetaClass, and MetaClass is also an instance of the root meta class. When you say that you inherit from NSObject, your class points to NSObject as your superclass. However, all meta classes direct to root metaclass as their superclass. All meta classes simply have a list of self-response methods. So when you send a message to a class object such as [NSObject alloc], and then actually objc_msgSend () will check the meta class to see if it responds to this method. If he finds a method, this Class object is the type of an instance object, and class is the type of a Class. For a complete OO, a class is also an object, and a class is an instance of the class type (MetaClass), so the class type description is meta class ).

5. Why do we inherit from Apple's class?

From the time you started Cocoa development, the tutorials mentioned here are like inheriting from NSObject and then writing some code. You enjoy the convenience of many classes inherited from Apple. One thing you never realized is that your object is set to use the OC runtime. When we allocate memory for an instance of our class, like this...

 
MyObject *object = [[MyObject alloc] init];
The first message to be executed is + alloc. If you look at the document, it says, "The isa instance variable of the new instance object is initialized to point to a data structure, which describes this class; other instance variables are initialized to 0." Therefore, the classes inherited from Apple not only inherit some important attributes, it also inherits the ability to easily allocate memory in the memory and creates an object structure that meets the runtime expectation in the memory (sets the isa pointer to our class ). 

6. What is the Class Cache? (Objc_cache * cache)

 

When OC runtime is checked along the isa pointer of an object, it will find that an object implements many methods. However, you may only call a small part of the method, and it does not make sense to search all selectors in the dispatch table of the class during each check. Therefore, this class implements a cache. When you search for the shard table of a class and find the proper selector, it will be put into the cache. So when objc_msgSend () searches for selector in a class, it first looks for the class cache. There is a theory that when you call a message on a class, you will probably call it later. So if we take this into consideration, it means that when we have a subclass inherited from NSObject called MyObject and run the following code:

 

MyObject *obj = [[MyObject alloc] init]; @implementation MyObject- (id)init {    if(self = [super init]) {        [self setVarA:@”blah”];        }    return self;}@end

(1) [MyObject alloc] is first executed. MyObject does not implement the alloc method, so we cannot find the + alloc method in this class, and then the superclass pointer will point to NSObject.

(2) Let's ask whether NSObject responds with the + alloc method. It can. + Alloc checks the Message Receiver class, which is MyObject, then allocates a memory space of the same size as our class, and initializes its isa pointer to the MyObject class, now we have an instance object, and finally add the + alloc method of the class Object to the NSObject class cache) (lastly we put + alloc in NSObject's class cache for the class object ).

(3) So far, we have sent a class message, but now we have sent an instance message, simply calling-init or the initialization method we designed. Of course, our class will respond to this method, so-(id) init is added to the cache. If MyObject implements the init method, it will add the init Method to the class cache of MyObject. If it is not implemented, this method is available only because of inheritance, the init method will still be added to the NSObject class cache ).

(4) then self = [super init] is called. Super is a magic keyword that points to the object's parent class, so we get NSObject and call its init method. This ensures that the inheritance function of OOP (Surface object programming) is normal. This method can correctly initialize the variables of the parent class, And then you (in the subclass) can initialize your own variables, if necessary, you can override the methods of the parent class. In the NSObject example, There is nothing important to do, but this is not always the case. Sometimes we need to perform some important initialization. For example...

 
#import @interface MyObject : NSObject { NSString *aString; } @property(retain) NSString *aString; @end @implementation MyObject -(id)init { if (self = [super init]) { [self setAString:nil]; } return self; } @synthesize aString; @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; id obj1 = [NSMutableArray alloc]; id obj2 = [[NSMutableArray alloc] init]; id obj3 = [NSArray alloc]; id obj4 = [[NSArray alloc] initWithObjects:@"Hello",nil]; NSLog(@"obj1 class is %@",NSStringFromClass([obj1 class])); NSLog(@"obj2 class is %@",NSStringFromClass([obj2 class])); NSLog(@"obj3 class is %@",NSStringFromClass([obj3 class])); NSLog(@"obj4 class is %@",NSStringFromClass([obj4 class])); id obj5 = [MyObject alloc]; id obj6 = [[MyObject alloc] init]; NSLog(@"obj5 class is %@",NSStringFromClass([obj5 class])); NSLog(@"obj6 class is %@",NSStringFromClass([obj6 class])); [pool drain]; return 0; }
Now, if you are new to Cocoa, you may say: 
NSMutableArrayNSMutableArray NSArrayNSArrayMyObjectMyObject
But in fact:
 
obj1 class is __NSPlaceholderArray obj2 class is NSCFArray obj3 class is __NSPlaceholderArray obj4 class is NSCFArray obj5 class is MyObject obj6 class is MyObject
 

This is because in Objective-C, the + alloc method may return the object of a class, and then return the object of another class in-init.
If you are interested, you can read these two articles: Class Clusters, Make Your Own Abstract Factory Class Cluster in Objective-C. The second article needs to bring Your Own small ladder .)

7. What happened in objc_msgSend?
In fact, many things have happened in objc_msgSend. Suppose we have such code...

 
[self printMessageWithString:@"Hello World!"];
It is actually translated by the compiler... 
objc_msgSend(self,@selector(printMessageWithString:),@"Hello World!");

We can query the isa pointer of the target object to see if the object responds @ selector (printMessageWithString :) selector. Suppose we find this selector in the sub-table or cache of the class, and we will execute it along the function pointer. In this way, objcmsgSend () will never be returned. It starts to execute, points to the pointer of the method, and then returns your method. In this way, it seems that the objcmsgSend () method has returned. Bill Bumgarner tells me more details about objc_msgSend () (part 1, Part 2 and Part 3) than I do ).

To sum up what he said, and you have read the Objective-C runtime code...

Check ignored Selector and Short Circut -- obviously, if we are running in the garbage collection mechanism, we can ignore the call-retain,-release, and so on.

Check the nil object (target ). Unlike other languages, it is completely legal to send messages to nil in OC, and you may be willing to do so for some reason. Suppose we have a non-nil object, and then we continue...

Then we need to find IMP on this class, so we should first find it from the class cache. If so, we will jump along the pointer to this function.

If the IMP is not found in the cache, and then the sub-table of the class is searched, if so, it will jump along the pointer to this function.

If IMP is not found in the cache and class distribution table, we will jump to the forwarding mechanism. This means that your code is eventually converted into a C function by the compiler. The method you write will be like this...

-(int)doComputeWithNum:(int)aNum
Will be translated:
int aClass_doComputeWithNum(aClass *self,SEL _cmd,int aNum)
OC Runtime calls your method (call your methods) by calling the function pointer pointing to these methods (invoking ). Now, what I want to say is that you cannot directly call these translated methods, but the Cocoa framework provides a way to get function pointers...
int (computeNum *)(id,SEL,int);//methodForSelector is COCOA & not ObjC Runtime//gets the same function pointer objc_msgSend getscomputeNum = (int (*)(id,SEL,int))[target methodForSelector:@selector(    doComputeWithNum:)]; //execute the C function pointer returned by the runtimecomputeNum(obj,@selector(doComputeWithNum:),aNum);
In this way, you can directly access this function and call it directly at runtime. You can even use this function to avoid the dynamic features of runtime. If you absolutely need to ensure that a method is executed. Objective-C calls your method in this way, but uses objc_msgSend ().

VIII. Objective-C message forwarding
In Objective-C, it is completely legal (or even a potential design decision) to send messages to an object that does not know how to respond to this method ). One of the reasons in Apple's documents is to simulate multi-inheritance. Objective-C is not supported by native, or you may just want to abstract your design and hide other objects/classes that process these messages behind the scenes. This is very required by runtime. It does this.

1. Runtime checks the class cache and sub-table of your class and all parent classes, but does not find the specified method.

2. The OC Runtime will call + (BOOL) resolveInstanceMethod :( SEL) aSEL on your class. This gives you a chance to provide a method implementation and tell runtime that you have resolved this method. If it starts to search, this method will be found this time. You can implement it like this... Define a function...

void fooMethod(id obj, SEL _cmd){     NSLog(@"Doing Foo");}
Then you can use class_addMethod () to parse it like this...
+(BOOL)resolveInstanceMethod:(SEL)aSEL{    if(aSEL == @selector(doFoo:))    {            class_addMethod([self class],aSEL,(IMP)fooMethod,"v@:");            return YES;    }    return [super resolveInstanceMethod];}
"V @:" in the last part of class_addMethod () is the return and parameter type of the method. You can see the complete introduction in the Type Encoding section of the Runtime Guide.

3. The Runtime is then called-(id) forwardingTargetForSelector :( SEL) aSelector. This is to give you a chance (because we cannot parse this method (see #2 above) to direct Objective-C runtime to another object that can respond to this message, it is better to call this method before the expensive processing process call-(void) forwardInvocation :( NSInvocation *) anInvocation. You can implement it like this

- (id)forwardingTargetForSelector:(SEL)aSelector{    if(aSelector == @selector(mysteriousMethod:))    {                return alternateObject;    }    return [super forwardingTargetForSelector:aSelector];}
Obviously, you do not want to directly return self from this method. Otherwise, an endless loop may occur.

4. The last Runtime will attempt to call-(void) forwardInvocation :( NSInvocation *) anInvocation on the target object. If you have never seen NSInvocation, it is the object form of the Objective-C message. Once you have an NSInvocation, you can change everything about the message, including the target object, selector, and parameters. So you can do this...

-(void)forwardInvocation:(NSInvocation *)invocation{      SEL invSEL = invocation.selector;        if([altObject respondsToSelector:invSEL]) {                [invocation invokeWithTarget:altObject];        } else {                [self doesNotRecognizeSelector:invSEL];        }}
If you inherit from NSObject, the default-(void) forwardInvocation :( NSInvocation *) anInvocation implementation is just a simple call-doesNotRecognizeSelector :, you can cover this method in the last chance to do something. If you are interested in this content, see: http://www.cnblogs.com/biosli/p/NSObjectinherit2.html)
9. Non Fragile ivars (Modern Runtime) (Non-Fragile ivar)

We recently obtained the Non Fragile ivars concept in Modern Runtime. When compiling your class, the compiler generates an ivar layout that shows where your class can access your ivars and get pointers to your objects, view the offset between ivar and the starting byte of the object, and obtain the total bytes of the read variable type. So your ivar layout may look like this, and the number on the left is the byte offset.

We have the ivar layout of NSObject, And then we inherit from NSObject to expand it and add our own ivars. This works well before Apple releases an update, but after Mac OS X 10.6 is released

 

Your custom object is removed because we have an overlapping parent class. The only way to prevent this is if Apple sticks to the previous layout. If they do, their framework cannot be improved because their ivar layout is frozen. In fragile ivar, you have to re-compile the class that you inherited from the apple class to restore compatibility. So is it possible to generate a non-fragile ivar?

When non-fragile ivars are used, the compiler generates the same ivar layout as fragile ivars. However, when runtime detects an overlapping superclass, it adjusts the offset of the ivar you added to this class, so that the newly added part in the subclass is displayed.

10. Objective-C Associated object

Recently, association references were introduced in Mac OS X 10.6 snow leopard. Objective-C cannot dynamically add some attributes to objects, which is different from other languages that support this function. Therefore, you have to reserve space for future variables. In Mac OS X 10.6, the Runtime of Objective-C has been native to support this function. If we want to add variables to an existing class, it looks like this...

 
# Import // Cocoa # include // objc runtime api's @ interface NSView (CustomAdditions) @ property (retain) NSImage * customImage; @ end @ implementation NSView (CustomAdditions) static char img_key; // has a unique address (identifier)-(NSImage *) mimimage {return objc_getAssociatedObject (self, & img_key);}-(void) setCustomImage :( NSImage *) image {objc_setAssociatedObject (self, & img_key, image, OBJC_ASSOC IATION_RETAIN);} @ end objc_setAssociatedObject () options, which can be found in the runtime. h file. /* Associated Object support. * // * objc_setAssociatedObject () options */enum {OBJC_ASSOCIATION_ASSIGN = 0, priority = 1, priority = 3, OBJC_ASSOCIATION_RETAIN = 01401, OBJC_ASSOCIATION_COPY = 01403 };

These options have the same meanings as those in the @ property syntax.

Hybrid vTable Dispatch

If you have read the modern runtime code, you will find this (in the objc-runtime-new.m)

/************************************************************************ vtable dispatch* * Every class gets a vtable pointer. The vtable is an array of IMPs.* The selectors represented in the vtable are the same for all classes*   (i.e. no class has a bigger or smaller vtable).* Each vtable index has an associated trampoline which dispatches to *   the IMP at that index for the receiver class's vtable (after *   checking for NULL). Dispatch fixup uses these trampolines instead *   of objc_msgSend.* Fragility: The vtable size and list of selectors is chosen at launch *   time. No compiler-generated code depends on any particular vtable *   configuration, or even the use of vtable dispatch at all.* Memory size: If a class's vtable is identical to its superclass's *   (i.e. the class overrides none of the vtable selectors), then *   the class points directly to its superclass's vtable. This means *   selectors to be included in the vtable should be chosen so they are *   (1) frequently called, but (2) not too frequently overridden. In *   particular, -dealloc is a bad choice.* Forwarding: If a class doesn't implement some vtable selector, that *   selector's IMP is set to objc_msgSend in that class's vtable.* +initialize: Each class keeps the default vtable (which always *   redirects to objc_msgSend) until its +initialize is completed.*   Otherwise, the first message to a class could be a vtable dispatch, *   and the vtable trampoline doesn't include +initialize checking.* Changes: Categories, addMethod, and setImplementation all force vtable *   reconstruction for the class and all of its subclasses, if the *   vtable selectors are affected.**********************************************************************/

The idea behind this is that runtime tries to store recently called selectors in this vtable, which can speed up your application, because it uses fewer commands (fewer instructions) than objc_msgSend ). The vtable stores 16 global most frequently called selectors. In fact, you can find the default selectors of garbage collection and non-garbage collection programs following the Code:

 

static const char * const defaultVtable[] = {    "allocWithZone:",     "alloc",     "class",     "self",     "isKindOfClass:",     "respondsToSelector:",     "isFlipped",     "length",     "objectForKey:",     "count",     "objectAtIndex:",     "isEqualToString:",     "isEqual:",     "retain",     "release",     "autorelease", };static const char * const defaultVtableGC[] = {    "allocWithZone:",     "alloc",     "class",     "self",     "isKindOfClass:",     "respondsToSelector:",     "isFlipped",     "length",     "objectForKey:",     "count",     "objectAtIndex:",     "isEqualToString:",     "isEqual:",     "hash",     "addObject:",     "countByEnumeratingWithState:objects:count:", };
You can find the methods in the stack tracing during debugging and use them for debugging like objc_msgSend.
Summary
OC Runtime is an excellent work. It has done a lot of work to support our Cocoa/Objective-C app and many excellent features. You can refer to the official documents of Apple to learn more (Objective-C Runtime Programming Guide and Objective-C Runtime Reference ).

In the last few words, programmers, most of the above are written by others. The reason why I chose originality is that I cannot find the original author .... So if the original author sees it, don't say I am using it. Leave a message for me. I will mark the source at the top .... Also, I really want to learn about the Runtime under OC. I mind if you buy a book called Objective-C 2.0. Very good ....

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.