IOS Run-time app

Source: Internet
Author: User
Tags new set

First, what is the runtime (runtime)?

Runtime is the pure C-language development library provided by Apple (Runtime is the underlying technology often used in development)
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 "CKPerson.h" #import <objc/runtime.h> intMainintargcConst Char* argv[]) {@autoreleasepool {number of//member variables        unsigned intOutcount =0;//Get all the member variables        //Ivars is a pointer to a member variable        //ivars default to NO. 0 member variableIvar *ivars = Class_copyivarlist ([Ckperson class], &outcount);//Traversal of all member variables         for(inti =0; i<outcount; i++) {//Remove member variables corresponding to position I//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 words such as copy\new\retain\create, then the data returned by this function will need to be released manuallyFree (ivars);//Ivar Ivar = *ivars;//Ivar ivar2 = * (Ivars + 1);//NSLog (@ "%s%s", Ivar_getname (Ivar), Ivar_getname (IVAR2));        //A Ivar represents a member variable        //int *p; A variable that points to type int        //Ivar *ivars; A variable that points to a Ivar type}return 0;}

2. Get the name of the uitextfiled member variable

// 成员变量的数量    unsignedint0;    // 获得所有的成员变量    class], &outCount);    // 遍历所有的成员变量    for (int0; i<outCount; i++) {        // 取出i位置对应的成员变量        Ivar ivar = ivars[i];        // 获得成员变量的名字        NSLog(@"%s", ivar_getName(ivar));    }    // 如果函数名中包含了copy\new\retain\create等字眼,那么这个函数返回的数据就需要手动释放    free(ivars);

Iv. 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);ObjectsClassesMetaClasses

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.

typedefstruct 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(idselfint 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 to create an 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_exchangeImplementationsobjc

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:
Class Stringclass = nsclassfromstring (@ "NSString")
So we got a string class. Next:
NSString *mystring = [Stringclass stringwithstring:@ "Hello World"];
Why did you do it? 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 datainchObject) {if([[Data type] isequaltostring:@ "String"]) {[self parsestring:[data value]]; }Else if([[Data type] isequaltostring:@ "number"]) {[self parsenumber:[data value]]; }Else if([[Data type] isequaltostring:@ "Array"]) {[self parsearray:[data value]]; }}}-(void) Parseobjectdynamic: (ID) Object { for(ID datainchObject) {[Self performselector:nsselectorfromstring ([NSString stringwithformat:@"parse%@:", the [datatype]]) withobject:[data value]]; }}-(void) parsestring: (NSString *) astring {}-(void) Parsenumber: (NSString *) anumber {}-(void) Parsearray: (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>  @interface nsmutablearray (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 {[ SelfLogaddobject: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@selector(myDynamicMethod)) {        class_addMethod(self"[email protected]:");        returnYES;    }    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 _selfNSString *string) {    NSLog(@"Hello %@"@selector"[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.

IOS Run-time app

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.