Runtime (IOS)

Source: Internet
Author: User
Tags new set

Runtime (IOS) First, what is the runtime (runtime)?
    • Runtime is the pure C-language development library provided by Apple (Runtime is a very good, often used in the development of the underlying technology)
Second, the role of the run time?
    • To get all the member variables of a class
    • To get all the properties of a class
    • Can get all the methods of a class
    • Exchange Method implementation
    • Ability to dynamically add a member variable
    • Ability to add a property dynamically
    • Ability to add a method dynamically
Iii. case: Get member variable name at run time
    • 1. Analysis
#import <Foundation/Foundation.h>#import"XMGPerson.h"#import <objc/runtime.h>IntMain(int argc,Constchar * argv[]) {@autoreleasepool {Number of member variablesUnsignedint outcount =0;Get all the member variablesIvars is a pointer to a member variableIvars default to NO. 0 member variable (front) Ivar *ivars = Class_copyivarlist ([XmgpersonClass], &outcount);Iterate through all the member variablesfor (int i = 0; i<outCount; i++) { //remove the member variables corresponding to the I position //Ivar Ivar = * (Ivars + i); Ivar Ivar = ivars[i]; //get the name of the member variable NSLog (@ "%s", Ivar_getname (Ivar));} //If the function name contains copy\new\retain\create and so on, then the data returned by this function will need to be manually released free (Ivars); Span class= "hljs-comment" >//Ivar Ivar = *ivars; //Ivar ivar2 = * (Ivars + 1); //NSLog (@ "%s%s", Ivar_getname (Ivar), Ivar_getname (IVAR2)); //a Ivar on behalf of a member variable //int *p; A variable that points to type int //Ivar *ivars; Variable pointing to Ivar type} return 0;}       
    • 2. Get the name of the uitextfiled member variable

Snip20151027_1.png
// 成员变量的数量    unsigned int outCount = 0;    // 获得所有的成员变量 Ivar *ivars = class_copyIvarList([UITextField class], &outCount); // 遍历所有的成员变量 for (int i = 0; i<outCount; i++) { // 取出i位置对应的成员变量 Ivar ivar = ivars[i]; // 获得成员变量的名字 NSLog(@"%s", ivar_getName(ivar)); } // 如果函数名中包含了copy\new\retain\create等字眼,那么这个函数返回的数据就需要手动释放 free(ivars);
Four, iOS bottom 1, the Runtime simple introduction
    • Objective-c is a simple language, 95% is C. Just add some keywords and grammar to the language level. What really makes Objective-c so powerful is its runtime. It's small but very powerful. The core of it is message distribution.
Messages
    • Executing a method, some languages, the compiler performs some additional optimizations and error checking because the invocation relationship is straightforward and obvious. But for message distribution, it is less obvious. You do not have to know whether an object can handle a message before sending it. You send the message to it, it may be processed, or it may be transferred to another object for processing. A message does not have to correspond to a method, and an object may implement a method to handle multiple messages.
    • In Objective-c, the message is implemented by Objc_msgsend (), a runtime method, and a similar approach. This method requires a target,selector, and there are some parameters. In theory, the compiler simply executes the message distribution into objc_msgsend. For example, the following two lines of code are equivalent.
[array insertObject:foo atIndex:5];objc_msgSend(array, @selector(insertObject:atIndex:), foo, 5);
Objects, Classes, metaclasses
    • Most object-oriented languages have classes and objects concepts. Objects is generated by classes. But in objective-c, classes itself is also objects, and can handle messages, which is why there are class methods and instance methods. Specifically, the object in Objective-c is a struct (struct), and the first member is ISA, which points to its own class. This is defined in the objc/objc.h.
typedef struct objc_object {    Class isa;} *id;
    • The class of object holds a list of methods, as well as pointers to the parent class. But classes is also objects, there will be an Isa variable, then where does it point? This leads to a third type: metaclasses. A metaclass is pointed to Class,class and is pointed to object. It holds a list of all the implemented methods, as well as the metaclass of the parent class. Read this article if you want to get a clearer idea of how objects,classes and metaclasses together workplace.
Methods, selectors and IMPs
    • We know that the runtime sends a message to the object. We also know that the class of an object holds a list of methods. How are these messages mapped to methods, and how are these methods executed?

    • The answer to the first question is simple. The class method list is actually a dictionary, and key is selectors,imps as value. An IMP is an implementation that points to the method in memory. It is important that the relationship between selector and Imp is determined at run time, not at compile time. So we can play some tricks.

    • IMP is usually a pointer to a method, the first argument is self, the type is ID, the second argument is _cmd, the type is sel, and the remainder is the parameter of the method. This is also where self and _cmd are defined. The following shows the method and Imp

- (id)doSomethingWithInt:(int)aInt{}id doSomethingWithInt(id self, SEL _cmd, int aInt){}
    • Now that we know objects,classes,selectors,imps and message distribution, what can the runtime do?
What can be done at runtime?
    • Role:

      • Create, modify, Introspect classes and objects
      • Message distribution
    • Message distribution has been mentioned before, but this is only a small subset of the functionality. All run-time methods have a specific prefix. Here are some interesting ways to do this:

Class
    • Class begins with a method to modify and Introspect classes.
    • Methods such as:
      • To get all the content of a class
        class_addIvar, class_addMethod, class_addProperty和class_addProtocol允许重建classes。class_copyIvarList, class_copyMethodList, class_copyProtocolList和class_copyPropertyList
      • Return a single content
        class_getClassMethod, class_getClassVariable, class_getInstanceMethod, class_getInstanceVariable, class_getMethodImplementation和class_getProperty
      • Some common methods of introspection
        class_conformsToProtocol, class_respondsToSelector, class_getSuperclass
      • Create an Object
        class_createInstance来创建一个object
Ivar
    • These methods allow you to get names, memory addresses, and objective-c type encoding.
Method
    • These methods are mainly used for introspection, such as:
method_getName, method_getImplementation, method_getReturnType等等
    • There are also some methods of modification, including:
      method_setImplementation和method_exchangeImplementations
ObjC
    • Once you've got the object, you can do some introspection and modification on it. You can get/set Ivar, use Object_copy and object_dispose to copy and free object memory. Instead of getting a class, you can use Object_setclass to change the class of an object.
Property
    • Property holds a large part of the information. In addition to getting a name, you can also use Property_getattributes to discover more information about the property, such as the return value, whether it is atomic, getter/setter name, whether it is dynamic, the Ivar name used behind it, is a weak reference.
Protocol
    • Protocols is a bit like classes, but the Lite version, the runtime method is the same. You can get the method, property, protocol list, and check if other protocol are implemented.
Sel
    • Finally we have some ways to deal with selectors, such as getting a name, registering a selector, and so on.
2. What can I do when I run? (for example) 2.1 Classes and selectors from Strings
    • A dynamic feature of the comparison base is the generation of classes and selectors by string. Cocoa provides the nsclassfromstring and Nsselectorfromstring methods, which are simple to use:

      NSClassFromString(@"NSString")
    • So we got a string class. Next:

      NSString *myString = [stringclass stringWithString:@"Hello World"];
    • 为什么要这么做呢?Is it more convenient to use class directly? This is usually the case, but there are scenarios where this method can be useful. First, it is possible to know if there is a class,nsclassfromstring that returns nil if the class does not exist at runtime.

    • Another usage scenario is to return a different class or method based on different inputs. For example, if you are parsing some data, each data item has a string to parse and its own type (String,number,array). You can do this in one way, or you can use multiple methods. One of the methods is to get the type and then use if to invoke the matching method. The other is to generate a selector based on the type, and then call it. Here are two ways to achieve this:

- (void) Parseobject: (ID) Object {for (ID dataIn object) {if ([[Data type] isequaltostring:@ "String"]) {[Self parsestring:[data value]]; }Elseif ([[Data type] isequaltostring:@ "Number"]) {[Self parsenumber:[data value]]; }Elseif ([[Data type] isequaltostring:@ "Array"]) {[self parsearray:[data value]];}}} -(void) parseobjectdynamic: (id) object { for (id data in object) {[self performselector:nsselectorfromstring ([ nsstring stringwithformat:@ "parse%@:", [Data type]]) Withobject:[data value]]; }}-(void) parsestring: (nsstring *) aString {}-(void" Parsenumber: (nsstring *) anumber {}-(nsstring *) Aarray {}       
    • As you can see, you could turn the code with the IF in line 7 into 1 lines. If there is a new type in the future, simply add the implementation method instead of adding the new else if.
2.2 Method Swizzling
    • As we have said before, the method consists of two parts. Selector equivalent to a method of id;imp is the implementation of the method. One of the conveniences of such separation is that the correspondence between selector and IMP can be changed. For example, an IMP can have multiple selectors pointing to it.

    • The method swizzling can exchange two implementations. Maybe you'll ask, "What's the situation that will require this?" ”。 Let's look at the two ways of extending class in Objective-c. The first is subclassing. You can override a method to invoke the implementation of the parent class, which also means that you must use the subclass instance, but if you inherit a cocoa class, cocoa returns to the original class (such as Nsarray). In this case, you will want to add a method to Nsarray, that is, use category. 99% of cases This is OK, but if you rewrite a method, there is no chance to invoke the original implementation.

    • Method swizzling can handle this problem. You can override a method without inheriting it, and you can invoke the original implementation. A common practice is to add a method to the category (or a whole new class, of course). The implementation can be exchanged by method_exchangeimplementations this run-time method. To see a demo, this demo demonstrates how to rewrite the AddObject: method to record every newly added object.

#import<objc/runtime.h>@interfaceNsmutablearray (Loggingaddobject)-(void) Logaddobject: (ID) aobject; @end  @implementation nsmutablearray (loggingaddobject) + (void) load { Method AddObject = Class_getinstancemethod (self,  @selector ( AddObject:)); Method logaddobject = Class_getinstancemethod (self, @ Selector (logaddobject:)); Method_exchangeimplementations (AddObject, logaddobject);} -(void) Logaddobject: (id) aobject {[ self Logaddobject:aobject]; nslog (@ "Added object%@ to Array%@", Aobject, self);}  @end             
    • We put the method exchange into load, and this method is only called once and is loaded at runtime. If you point to a temporary use, you can put it somewhere else. Notice a very obvious recursive call to Logaddobject:. This is where method swizzling easy to confuse us, because we have exchanged the implementation of the methods, so actually the call is AddObject:
Dynamic inheritance, Exchange
    • We can create a new class at run time, which isn't used much, but it's still very powerful. You can create new subclasses through it and add new methods.

    • But what is the use of such a subclass? Don't forget a key point of objective-c: There is a variable inside object called Isa that points to its class. This variable can be changed without having to recreate it. Then you can add new Ivar and methods. You can modify the class of an object with the following command.

      object_setClass(myObject, [MySubclass class]);
    • This can be used in key Value observing. When you start observing an object, cocoa creates the subclass of the object's class, and then points the object's Isa to the newly created subclass.

Dynamic method Processing
    • So far, we have discussed method exchange and the processing of existing methods. So what happens when you send a message that an object cannot handle? It is obvious that "it breaks". This is true in most cases, but cocoa and runtime also provide some coping options.

    • The first is the dynamic method processing. Typically, a method is processed, and the runtime looks for a matching selector and executes it. Sometimes you just want to create a method at run time, for example, some information is only available at run time. To achieve this effect, you need to rewrite +resolveinstancemethod: and/or +resolveclassmethod:. If you do add a method, remember to return yes.

+ (BOOL)resolveInstanceMethod:(SEL)aSelector {    if (aSelector == @selector(myDynamicMethod)) {        class_addMethod(self, aSelector, (IMP)myDynamicIMP, "[email protected]:"); return YES; } return [super resolveInstanceMethod:aSelector];}
    • What scenario will the cocoa use these methods? Core data is used a lot. Nsmanagedobjects has many properties that are added at run time to handle Get/set properties and relationships. What if the model is changed at run time?
Message forwarding
    • If Resolve method returns no, the runtime goes to the next step: message forwarding. There are two common use cases. 1) forward the message to another object that can process the message. 2) forward multiple messages to the same method.

    • Message forwarding is a two-step phase. First, the runtime calls-forwardingtargetforselector: If you just want to send the message to another object, use this method because it is more efficient. If you want to modify the message, then use-forwardinvocation: The runtime packages the message into nsinvocation and returns it to you for processing. After processing, call Invokewithtarget:.

    • Cocoa has several places where message forwarding is used, the main two places are proxies (Proxies) and response chains (Responder Chain). Nsproxy is a lightweight class that works by forwarding messages to another object. It is useful if you want to lazily load a property of object. Nsundomanager also works, but intercepts messages, then executes them, rather than forwarding them to other places.

    • The response chain is about how cocoa handles and sends events and behaviors to the corresponding object. For example, using cmd+c executes the copy command, which sends-copy: to the response chain. First Responder, usually the current UI. If the message is not processed, it is forwarded to the next-nextresponder. Keep going until you find an object that can handle the message, or you can't find it, error.

Use block as Method IMP
    • IOS 4.3 brings a lot of new runtime methods. In addition to the enhancement of properties and protocols, a new set of methods to start with IMP is also brought. Typically an IMP is a pointer to a method implementation, with the first two arguments being object (self) and selector (_cmd). IOS 4.0 and Mac OS X 10.6 brought Block,imp_implementationwithblock () to allow us to use block as IMP, and the snippet below shows how to add a new method using block.
IMP myIMP = imp_implementationWithBlock(^(id _self, NSString *string) {    NSLog(@"Hello %@", string);});class_addMethod([MYclass class], @selector(sayHello:), myIMP, "[email protected]:@");
    • As you can see, the objective-c surface looks quite simple, but still very flexible, can bring many possibilities. The advantage of a dynamic language is that it does a lot of clever things without expanding the language itself. Key Value observing, for example, provides an elegant API that seamlessly integrates with existing code without the need for new language-level features.

Runtime (IOS)

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.