Runtime “,” practical English interview work I see ^_^..

Disclaimer: all my articles will be the first time I will appear in my [iOS + Programmer

Write in first the [written in the previous]


For iOS developers, when it comes to runtime, I would like to say that “runtime runtime” and the basic use of the method. I believe that many developers had the same with me, maybe when you use this important module to complete some tasks after (copy and paste ^_^.), still do not know runtime knowledge system and the inherent principle.

Runtime is more difficult in iOS programming module, want to learn the OC runtime is that you must be familiar with things, here is my runtime collection, from scratch, from the shallower to the deeper brought several application scenarios, and the actual development of the runtime.

This article mainly from the [runtime module practical] learning summary.
in the limited time and knowledge, the article is bound to have a summary of the “incomplete, inadequate” place, but also hope that the friends pointed out that in order to improve the quality of the article.

Runtime
–&gt Star;

Directory: runtime concept runtime message mechanism runtime method called “runtime” message flow mechanism running common development and application of runtime “
1.runtime” to master the work scene exchange method of
2.runtime
3.runtime dictionary to add the attribute classification dynamic rotation model (Runtime considers three cases) runtime runtime “interview” with other function of
1 add dynamic method
2 NSCoding automatic archiving file
3.runtime Class settlement of the operation of the
4.runtime method swizzling is a concept of what a few parameters (commonly known as dark) last interview questions notes expect &amp follow-up;

This article is a longer period, strongly recommended to every collection, in reading!

Runtime concept


Objective-C is based on C, which adds an object-oriented feature to C. It will be a lot of static language at compile and link time to do things to the runtime runtime to deal with, it can be said that runtime is our Objective-C behind the scenes workers.

  • Runtime (referred to as runtime), is a set of pure C (C and compilation of written) API. The OC is the run-time mechanism, that is, the run-time mechanism, the most important is the message mechanism.
  • For the C language, the function of the call at compile time will decide which function to call.
  • OC function calls to send messages, belonging to the dynamic call process. At compile time and can not decide which function to call, only when the actual operation will be based on the name of the function to find the corresponding function to call.
  • In fact, at compile time, OC can call any function, even if this function has not been achieved, as long as the statement will not error, only when the running time will Baocuo, this is because OC is the dynamic call operation. The C language calls the function will not be reported wrong.

Runtime message mechanism


We write OC code, it is also running into a runtime mode of operation. Any way to call the essence: is to send a message (using runtime to send messages, the realization of the OC through the runtime implementation).

The principle of message mechanism: the object according to the method number SEL to the mapping table to find the corresponding method to achieve.

Every OC method, the underlying must have a corresponding runtime method.

Runtime
OC–> runtime

A simple example:
validation: the method call, whether it is really converted to a message mechanism?

  • You must import the header file #import < objc/message.h> note 1: we import the system header file, usually with a bracket. Note 2:OC message mechanism method to find build setting -&gt [prompting step search; MSG -> objc_msgSend (NO)] Note 3: final message mechanism, the compiler do the final code, need to recompile the current code, Xcode compiler, -rewrite-objc [clang main.m] to see the final generated code, example: CD main.m –> front input instruction, will generate the.Opp file (C++ code) Note 4: here is generally not directly into the < objc/runtime.h>
    Runtime
    message.h
  • Example code: OC method –> runtime method
Description: eat (no reference) and run (Shen) is a private method "Person model in the class can help me call a private method"; / / Person *p = [Person alloc]; / / Person *p at the bottom of the actual writing (objc_getClass = objc_msgSend ("Person"), sel_registerName ("alloc")); / / P [p = init]; P = objc_msgSend (P, sel_registerName ("init")); / / call object method (essence: let the object sends a message to //[p eat]); / / Essence: let the class object send message objc_msgSend (P, @selector (eat)); objc_msgSend ([Person class], @selector (run:), 20); //--------------------------- < # I line #> / / ------------------------------// may the good understanding of a / / ID objc = [NSObject alloc]; ID objc = objc_msgSend (NSObject [class], @selector (alloc)); / / objc = [objc init]; ob JC = objc_msgSend (objc, @selector (init));

Runtime method call process message mechanism


Interview: message mechanism call procedure

  • How to call the eat method, object method: (list method save to a class object), methods: ((Meta Class) to save the metaclass method list). 1.OC sends a message to an object, the runtime library will be based on the object’s isa pointer to find the object corresponding to the class or the parent class search method.. 2 registration method number (here with the method of the number of benefits, you can quickly find). 3 according to the number of methods to find the corresponding method. 4 find only the final function to achieve the address, according to the address to call the corresponding function.
  • What does a pointer to a objc object point to isa? What is the role? Each object has an internal isa pointer, the pointer is the true type of it, according to which the pointer can know which class to call the future method.

Runtime common role


  • The realization of two methods of dynamic exchange
  • Add attributes dynamically
  • Automatic conversion of the dictionary conversion model
  • send message
  • Dynamic addition method
  • Intercept and replace method
  • Automatic archiving and reconciliation of NSCoding

Runtime commonly used in the development and application of the scene “work master”


Runtime switching method

Application scenarios: when the third party framework or system native method function can not satisfy us, we can keep the original method of the system based on the function to add additional features.

Requirements: load a picture directly with [UIImage imageNamed:@ “image”]; is unable to know exactly whether there is loading success. Add additional functionality to the system’s imageNamed (whether to load the picture successfully).

  • Program 1: the class of the system, rewrite the method
  • Program two: use runtime, exchange method

Implementation steps:

  • 1 add a taxonomy to the system method
  • 2 to achieve their own with an extension of the function of the method
  • 3 exchange method, only need to exchange,

Case code: Method + call + print output

- (void) viewDidLoad {[super viewDidLoad]; / / program: first make a classification, the definition of a method can load pictures and print + (instancetype) imageWithName: (NSString * name); / / scheme two: to achieve the exchange of imageNamed and ln_imageNamed, you can call imageNamed, indirect call ln_imageNamed. UIImage *image [UIImage imageNamed:@ = "123"]}; #import < objc/message.h> @implementation; UIImage (Image) load / * * method: called when the class is loaded into memory, only one method call should exchange to call * + (void) load {/ / 1 / / class_getClassMethod (imageNamed access method. Acquisition method of a class of Method = class_getClassMethod (self) imageNamedMethod, @selector (imageNamed:)); / / the 2 methods of ln_imageNamed extraction ln_imageNamedMethod address Method = class_getClassMethod (self, @selector (ln_imageNamed:)); / / the 3 exchange address, equivalent exchange mode; "method_exchangeImplementations" to achieve the exchange of two methods (imageNamedMethod, method_exchangeImplementations ln_imageNamedMethod);} See below / * * is not a dead loop calls the imageNamed => ln_imageNamed called ln_imageNamed => imageNamed; * / / / and to determine whether the loading picture loaded successfully + (UIImage *) ln_imageNamed: (NSString * name) {UIImage *image = [UIImage ln_imageNamed:name]; if (image) {NSLog (@ runtime to add extra functions - loaded successfully ");} else {NSLog (@ runtime to add extra functions -- failed to load");} return image;} / * * cannot override classification in imageNamed system, because it will make the function of the system covered, and so could not call the super classification in the second step, we should realize their own with an extended function methods. + (UIImage *) imageNamed: (NSString * name) {} * / @end / / 2017-02-17 17:52:14 print output .693 runtime[12761:543574] runtime add additional features - loaded successfully

Summary: what we do is in the third step of the method call process, the exchange of the address of the two methods. And we change the way we want to call the imageNamed: method in the system, so we write the code in the classified load method. Finally, when the system is running, the method of the system will find the realization of our method.

Runtime adds attributes to the class dynamically

Principle: to declare a class attribute, in fact, is to add to the association of this class, not directly to the value of the memory space to add to the class storage space.

Application scenarios: to add attributes to the class of the system, you can use runtime to add dynamic attributes. Note: the
system NSObject add a classification, we know that the classification is not able to add member properties, although we used @property, but it will automatically generate get and set method statement, and no underlined properties and methods of generation. But we can do it by runtime to achieve it.

Requirements: dynamically add name string to the system NSObject class.

Case code: Method + call + Print

@interface NSObject (Property) / @property classification: will only generate get, set method statement does not generate, will not generate a @property NSString *name underline member properties; @property NSString *height; @end @implementation NSObject (Property) - (void) setName: (NSString * name) {/ / objc_setAssociatedObject (a value to an object associate a value stored in an object to which object) / / object: / / key: / / add attribute attribute name value: attribute value preservation strategy (self objc_setAssociatedObject / / policy:, @ "name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);} - (NSString * name) {return (self, objc_getAssociatedObject @ name);} / / *objc = [[NSObject alloc] called NSObject init]; objc.name = @ NSLog @ ("123" " Runtime, objc.name dynamically add the attribute name==%@ "); / / 2017-02-17 19:37:10.530 runtime[12761:543574] runtime print output dynamic add the attribute --name = = 123

Summary: in fact, the essence of attribute assignment, is that an object associated with the attribute, so name attribute assignment for NSObject classification is to make name and NSObject associated, while runtime can do it.

Runtime dictionary transfer model

Dictionary to model approach:

  • One for the model attribute assignment (beginners).
  • Dictionary model KVC to achieve KVC dictionary turn model drawbacks: we must ensure that the attributes of the model and the corresponding key in the dictionary. If not, it will call [< Status 0x7fa74b545d60> setValue:forUndefinedKey:] reported that key could not find the error. Analysis: the attributes of the model and the key of the dictionary do not correspond to each other, the system will call the setValue:forUndefinedKey: error. Solution: rewrite the object of setValue:forUndefinedKey:, the method of the system coverage, you can continue to use KVC, the dictionary turn model.
  • The dictionary to realize the Runtime model ideas: the use of operation, all the properties of ergodic model, according to the attribute name model, to find out the key dictionary, a value corresponding to the attribute assignment model (from reminder: Dictionary values do not have to take out all). Consider the situation: 1 when the dictionary of the key and the model does not match the attributes. 2 nested model in the model (the model property is another model object). 3 array with model (model attribute is an array, the array is a model object). Note: according to the above three special cases, the first dictionary key and the model of the property should not be the case. It should have two kinds, one is the keys of the dictionary is greater than the model number of attributes, then we don’t need any treatment, because the runtime is the first traversal model all properties to the dictionary according to the attribute name to find the corresponding value assignment, the excess value is not to see; another is greater than the number of attribute model the keys of the dictionary on, this time because of property has no corresponding value will be set to nil, will lead to crash, we only need to add a judgement. Consider the following three cases one by one note: steps: to provide a NSObject classification, specialized dictionary transfer model, after all the models can be achieved through this classification dictionary model.
  • MJExtension dictionary model to achieve the bottom of the package is also on the runtime, it can be a model of all attributes to traverse. (the reason why you cannot read, MJ encapsulates many layers. ^_^.).

Here for the dictionary to achieve the model KVC, do not explain, if you use the KVC or the realization of the principle is not very clear, you can refer to the utility of the KVC encoding & KVO monitor

Dictionary Runtime model to achieve:
Description: the following example is to consider the three cases included in the conversion example, the specific can be annotated on the picture

Runtime
Runtime dictionary transfer model

1, runtime dictionary transfer model –> dictionary of key and the model does not match the properties of the model number of attributes is greater than the dictionary key logarithm, this situation is dealt with as follows:

According to the model / / Runtime: attributes to remove the corresponding dictionary value assigns the model attributes all attributes of ideas: / / -> traversal model; use the runtime (instancetype) + modelWithDict: (NSDictionary * dict) {/ / 1 to create a corresponding object ID objc [[self = alloc] init]; / / the 2 by runtime to members in the object assign class_copyIvarList: to get all the members of Ivar / * * attribute class: member attributes mean the first parameter: get the class in which the member properties of second parameters: said how many members of this class attribute, pass a variable Int address will automatically give the variable assignment return value Ivar *: refers to a a Ivar array, all member properties in an array, the returned array can obtain all To. The members of the count: variable number / unsigned int count = 0; / / get all the members of Ivar property in the class_copyIvarList class (*ivarList = self, & count); / / traversal of all member variables for (int i = 0; I < count; i++) {/ / according to the angle, take out the corresponding member of the Ivar Ivar attribute = ivarList[i] from the array; / / get the member variable name NSString *ivarName = [NSString stringWithUTF8String:ivar_getName (Ivar)]; / / handle member attribute names in the dictionary (key -> _ removed from the first corner, NSString *key began interception) = [ivarName substringFromIndex:1]; / / according to the members of the attribute name corresponding to search in the dictionary value ID value = dict[key] [/ /; if the model attribute is greater than the number of words The key of mathematical model code, the property will be assigned to nil] / / and the error (could not set nil as the value for the key age. if (value)) {/ / attribute assignment model to [objc setValue:value forKey:key] return objc;}}};

Note:
uses the runtime dictionary to get the model property name when it comes to the model, it is best to get the member property name Ivar because there may be a property that is not setter and “getter methods.


2, runtime dictionary transfer model –> model nested model “model property is another model object”, this situation is dealt with as follows:

(instancetype) + modelWithDict2: (NSDictionary * dict) {/ / 1 to create a corresponding object ID objc [[self = alloc] init]; / / the 2 using runtime to objects in unsigned int attribute assignment member count = 0; / / get all the members of Ivar property in the class_copyIvarList class (*ivarList = self, & count); / / traversal of all the member variable for (int i = 0; I < count; i++) {/ / according to the angle, take out the corresponding member of the Ivar attribute Ivar = ivarList[i] from the array; / / get the name NSString member variables *ivarName = [NSString stringWithUTF8String:ivar_getName] (Ivar); / / get the member variable type NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding (Ivar)]; @/: / / replace "User/" - > User ivarType = [ivarType stringByReplacingOccurrencesOfString:@ "/" withString:@ "]; ivarType [ivarType stringByReplacingOccurrencesOfString:@ =" @ "withString:@"]; / / processing member attribute name -> dictionary key *key = [ivarName NSString / / to the interception of substringFromIndex:1] from the first angle; / / according to members of the attribute name corresponding to the dictionary lookup in value ID value = dict[key]; / / two: if the dictionary and dictionary conversion, also need to put the corresponding dictionary into a model to judge whether value / / is the dictionary, and it is a custom object needs to be converted to if ([value isKindOfClass:[NSDictionary class]] & & hasPrefix:@ "NS" [ivarType! ") {/ / dictionary conversion model UserDict => User model, into which model generating class object Class / modelClass = NSClassFromString string based on the class name (ivarType); if (modelClass) {/ / has a corresponding model only need to turn to the dictionary to model value / / [modelClass modelWithDict2: = value];}} / / to the attribute assignment model if (value) {[objc setValue:value forKey:key] return objc;}}};

3, runtime dictionary conversion model of –> with an array of models “model attribute is an array, the array is the dictionary model object” in this case are as follows:

According to the model / / Runtime: attributes to remove the corresponding dictionary value assigns the model attributes all attributes of ideas: / / -> traversal model; use the runtime (instancetype) + modelWithDict3: (NSDictionary * dict) {/ / 1 to create a corresponding object ID objc [[self = alloc] init]; / / the 2 using runtime for object assignment the members of unsigned int attribute count = 0; / / get all the members of Ivar property in the class_copyIvarList class (*ivarList = self, & count); / / traversal of all member variables for (int i = 0; I < count; i++) {/ / according to the angle, take out the corresponding member of the Ivar attribute Ivar = ivarList[i] from the array; NSString *ivarName / / fetch the member variable name = [NSString stringWithUTF8String:ivar_getName (Ivar)]; The members of the attribute name -> / / treatment; in the dictionary (key _ removed from the first corner, NSString *key began interception) = [ivarName substringFromIndex:1]; / / according to the members of the attribute name corresponding to search in the dictionary value ID value = dict[key]; //--------------------------- & lt; # I line #> ------------------------------// / / / / three conversion: NSArray is the dictionary, the array dictionary into the model. If the value judgment / / is an array of if ([value isKindOfClass:[NSArray class]]) {/ / judgment has not achieved the corresponding class dictionary array to model an array of protocol / / arrayContainModelClass provides an agreement to abide by this Agreement, as long as the class, can put in the array dictionary conversion model If ([self respondsToSelector:@selector (arrayContainModelClass)]) {/ / convert ID type, can call any of the methods of the object ID idSelf = self; *type = [idSelf arrayContainModelClass][key] / NSString model to obtain the array corresponding to the dictionary; / / Class classModel = NSClassFromString generation model (type); NSMutableArray *arrM = [NSMutableArray array]; / / traversal dictionary, generation an array of for (NSDictionary *dict in model value) {/ / model = [classModel dictionary turn model ID modelWithDict3:dict]; [arrM addObject:model];} The model of array assignment to value / value = arrM;}} / / if the model attribute is greater than the number of pairs of mathematical model of attribute dictionary, will be assigned to nil, and the error of if (value) {/ / attribute assignment model to [objc setValue:value forKey:key] return objc;}}};
Runtime
runtime dictionary conversion model –> array with model output

Summary: if we can get to the type of attribute, it can capture the array attribute model, and then the array traversal and dictionary conversion model of each model, but we do not know in the array model is what type, we can declare a method, this method is not allowed to call it let the realization and return model.

Mentioned here if you are not very clear, it is recommended to refer to my Demo, the important part of the code has a corresponding annotation and text printing, running procedures can be very intuitive performance.

Runtime other role “interview familiarity”


Dynamic addition method

Application scenarios: if a class method is very much, when loading the class to the memory is also more expensive resources, the need to generate a mapping table for each method, you can use a dynamic class, add a solution.

Note: OC we are very used to lazy loading, when used to load it, but in fact as long as a class to achieve a method, it will be loaded into memory. When we do not want to load so many methods, it will use the runtime dynamic add method.

Requirements: runtime dynamic add method handles an invocation of an implementation method and removes the error.

Case code: Method + call + print output

- (void) viewDidLoad viewDidLoad] Person {[super = [[Person; *p alloc] init]; / / default person does not implement the run: method, can be called by performSelector, but will be in error. / / dynamic method will not add error [p performSelector:@selector (run:) withObject:@10] @implementation Person;} / / no return value, 1 Parameters / / void, (ID, SEL) void AAA (ID self, SEL _cmd, NSNumber *meter) {NSLog (@ "% @ run meter", meter);} / / any method there are two implicit default parameters, self, _cmd (serial number method of the current method) / / what calls: as long as an object is called an unrealized method will call this method, processing / role: dynamic add method, treatment did not achieve + (BOOL) resolveInstanceMethod: (SEL) {/ / SEL [NSStringFromSelector (SEL) isEqualToString:@ "run"]; if (SEL = = NSSelectorFromString (@ run:)) {/ / run / / class: to add dynamic methods which add methods which add / / SEL: Method, number is added / / method method IMP: method to realize => function; => function; => entrance; function name (function to add the method to realize (function address)) / / type: (return value type + parameter type) v:void @: object -> self: SEL-> _cmd (self, SEL, class_addMethod (IMP) AAA, "[email protected]: @"); return YES; return [super resolveInstanceMethod:sel]};} / / @end 2017-02-17 19:05:03.917 runtime[12761:543574] runtime print output dynamic adding method -- run 10 meters

Automatic archiving and reconciliation of NSCoding

If you implement custom model data persistence process, then you must understand that if a model has many attributes, so we need to achieve through the encodeObject and decodeObjectForKey methods for each attribute, if such a model and a lot, it really is a very troublesome thing. Here’s a simple way to see.

Suppose there is now a Movie class with 3 properties. Look at the.H file

If you want the file //1. / / Movie.h class can implement archiving and anti archiving, need to comply with an agreement NSCoding @interface Movie: NSObject< NSCoding> @property (nonatomic, copy) NSString *movieId @property (nonatomic, copy); NSString *movieName; @property (nonatomic, copy) NSString *pic_url; @end

If it is written properly,.M file should be like this:

The file @implementation / / Movie.m Movie - (void) encodeWithCoder: (NSCoder * aCoder) {[aCoder encodeObject:_movieId forKey:@ "Id"]; [aCoder encodeObject:_movieName forKey:@; [aCoder encodeObject:_pic_url "name" forKey:@ "URL"];} - (ID) initWithCoder: (NSCoder * aDecoder) {if (self = [super init]) {self.movieId = [aDecoder decodeObjectForKey:@ "Id"]; self.movieName [aDecoder decodeObjectForKey:@ = "name"]; self.pic_url [aDecoder decodeObjectForKey:@ = "URL"]}}; return self; @end

If there are 100 attributes, then we can only write to the 100 attributes again.

However, you can use runtime, there is a more convenient method, as follows.

#import "Movie.h" #import < objc/runtime.h> @implementation; Movie (void) encodeWithCoder: (NSCoder * encoder) {unsigned int count = 0; Ivar = *ivars class_copyIvarList ([Movie class], & count); for (int i = 0; i< count; i++) {/ / I remove members corresponding to the position of the variable Ivar Ivar = ivars[i]; / / view member variable const (Ivar) char *name = ivar_getName; *key = [NSString stringWithUTF8String:name] / / NSString file; ID value = [self valueForKey:key]; [encoder encodeObject:value forKey:key];}}; free (Ivars) - (ID) initWithCoder: (NSCoder * decoder) {if (self = [super init]) {unsigned int count Ivar = 0; *ivars = class_copyIvarList ([M Ovie class], & count); for (int i = 0; i< count; i++) {/ / I remove members corresponding to the position of the variable Ivar Ivar = ivars[i]; / / view member variable const (Ivar) char *name = ivar_getName; *key = [NSString stringWithUTF8String:name] / / NSString file; ID value = [decoder decodeObjectForKey:key]; / / set the body [self setValue:value forKey:key] member variable free (Ivars);}}}; return self; @end

This way, no matter how many properties, write these lines of code to get the. How, the code is a little more,
say the following to see a more simple way: two code.

#import "Movie.h" #import < objc/runtime.h> #define; encodeRuntime (A) int / unsigned / count / Ivar = 0; *ivars = class_copyIvarList ([A class], & count); for (int / I = 0; i< count; i++) {/ Ivar Ivar = ivars[i]; *name = ivar_getName (const / char Ivar *key = [NSString / NSString); stringWithUTF8String:name]; ID / value = [self / valueForKey:key]; [encoder encodeObject:value forKey:key];}/ / free (Ivars); / / #define / / initCoderRuntime (A) if (self = [super init]) {/ unsigned int count = 0; *ivars = Ivar / class_copyIvarList ([A, class], & count) (int / for; I = 0; i< count; i++) {/ Ivar Ivar = ivars[i]; *name = const / char / ivar_getName (Ivar); NSString *key = [NSString / id = [decoder stringWithUTF8String:name]; value decodeObjectForKey [self / setValue:value: key]; forKey:key];}/ / free (Ivars / return);}/ self; / / @implementation Movie - (void) encodeWithCoder: (NSCoder * encoder) {encodeRuntime} (Movie) - (ID) initWithCoder: (NSCoder *) decoder initCoderRuntime (Movie) {@end}

Optimization: above is the encodeWithCoder and initWithCoder these two methods into macro. We can put these two macros into a single file, where the data persistence model can be directly used by the following two macros.

Runtime under the Class operation

The following is a common method of runtime under Class and with the use of sample code. The operation, [reproduced original] http://www.jianshu.com/p/46dd81402f63

Unsigned int count;

  • Get the objc_property_t *propertyList attribute list = class_copyPropertyList ([self, class], & count for (unsigned); int i=0; i< count; i++) {const char *propertyName = property_getName (propertyList[i]); NSLog (@ property—-& GT, [NSString stringWithUTF8String:propertyName];% @ “);}
  • A list of Method *methodList class_copyMethodList acquisition method ([self = class], & count for (unsigned); int i; i< count; i++) {Method method = methodList[i]; NSLog (@ method—-> NSStringFromSelector (% @ “, method_getName (method)));}
  • Get a list of Ivar *ivarList class_copyIvarList member variables ([self = class], & count for (unsigned); int i; i< count; i++) {Ivar myIvar = ivarList[i]; const = char *ivarName ivar_getName (myIvar); NSLog (@ Ivar—-> [NSString, stringWithUTF8String:ivarName]% @ “);}
  • A list of __unsafe_unretained Protocol acquisition protocol **protocolList = class_copyProtocolList ([self class], & count for (unsigned); int i; i< count; i++) {Protocol *myProtocal = protocolList[i]; const = char *protocolName protocol_getName (myProtocal); NSLog (@ protocol—-> [NSString, stringWithUTF8String:protocolName]% @ “);}

Now there is a Person class, and person created by the Xiaoming object, there are two methods of test1 and test2

  • Obtain class Class PersonClass = object_getClass ([Person class]); SEL oriSEL = @selector (test1); Method oriMethod = _class_getMethod (xiaomingClass, oriSEL);
  • Method of obtaining examples Class PersonClass = object_getClass ([xiaoming class]); SEL oriSEL = @selector (test2); Method cusMethod = class_getInstanceMethod (xiaomingClass, oriSEL);
  • Add method BOOL addSucc = class_addMethod (xiaomingClass, oriSEL, method_getImplementation (cusMethod), method_getTypeEncoding (cusMethod));
  • Replace the original method to achieve class_replaceMethod (toolClass, cusSEL, method_getImplementation (oriMethod), method_getTypeEncoding (oriMethod));
  • Exchange of two methods to achieve method_exchangeImplementations (oriMethod, cusMethod);
Runtime several parameter concepts

The above several methods should be regarded as the actual situation in the runtime application of the majority of the situation, the usual code is almost enough to use.
here in the runtime parameters of several concepts, do a simple description

1, objc_msgSend
this is the most basic function for sending messages.
in fact, the compiler will select one of the four methods in the objc_msgSend, objc_msgSend_stret, objc_msgSendSuper, or objc_msgSendSuper_stret. If the message is passed to the superclass, then the name with the Super function will be called; if the return value is a data structure rather than a simple value, then the name will be called with a stret function.

2, SEL
objc_msgSend function of the second parameter type is SEL, it is selector in Objc in the type of representation (Swift is the Selector class). Selector is the method selector, can be understood as the distinguish method of ID, and the data structure of the ID is SEL:
typedef struct objc_selector *SEL
; in fact it is mapped to the C string method, you can use the command @selector (sel_registerName) Objc compiler function ` ` or Runtime system to obtain a SEL type method selector.

3 ID
objc_msgSend, the first parameter is of type ID, which people are not unfamiliar, it is a pointer to a pointer to an instance of a class:
typedef struct objc_object *id and
objc_object; what is that:
struct objc_object {Class isa;};
objc_object structure contains a pointer to a ISA, according to isa the pointer can follow it to find objects belonging to the class.

4, the definition of runtime.h in Class

Struct objc_class {Class isa OBJC_ISA_AVAILABILITY; / / Class each have a pointer to a isa #if __OBJC2__ Class super_class! OBJC2_UNAVAILABLE const char *name; / / parent class OBJC2_UNAVAILABLE; / / Version / / long class OBJC2_UNAVAILABLE class long info version; OBJC2_UNAVAILABLE; / / *!! for the use of some of the bit operation period. Such as: CLS_CLASS (0x1L) said the class is class; CLS_META (0x2L) said the metaclass (runtime.h long instance_size OBJC2_UNAVAILABLE detailed list); / / struct objc_ivar_list *ivars OBJC2_UNAVAILABLE case size; / / storing each instance variable memory address struct objc_method_list **methodLists OBJC2_UNAVAILABLE; / / *!! according to info information sure is a class or instance, run struct objc_cache *cache what function method OBJC2_UNAVAILABLE struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; / / cache protocol; / / #endif} OBJC2_UNAVAILABLE;

It can be seen that a class has also been associated with its superclass pointer, class name, member variables, methods, caching, and attached protocols.
in the objc_class structure: `ivars is a objc_ivar_list pointer; methodLists is a pointer to the objc_method_list pointer. That is, you can dynamically modify the value of *methodLists to add the member method, which is the principle of Category` implementation.

All the things mentioned above are in Demo, if you feel it is difficult to understand, it is strongly recommended that you download the Demo, run the code and text annotation, the effect will be better, if you feel good, please for my Demo star a.

What is method swizzling (commonly known as black magic)

  • Simply to say that the exchange of methods
  • In the Objective-C call a method, in fact, is to send a message to an object, the only basis for finding the message is the name of the selector. The dynamic characteristics of Objective-C, can achieve the corresponding selector method change at run time, to reach the purpose of hook method
  • Each class has a list of methods, mapping a name and storage methods to achieve, the essence of selector is actually the method name, IMP is a function pointer, pointing to the Method implementation, the selector can be found in the corresponding IMP.
Runtime
selector –> corresponding IMP
  • The replacement method using class_replaceMethod realization of the use of a method of setting method_setImplementation to IMP several direct exchange method is implemented using the method_exchangeImplementations exchange method two.
    Runtime
    switching method

Here you can refer to Jane friend this: [Runtime Method Swizzling development example summary] http://www.jianshu.com/p/f6dad8e1b848

Here you can refer to the authority of this article: OC run black magic Method Swizzling

Runtime
— black don’t go, I will bite to eat you!

Comment on the last interview


What does the following code output?

@implementation Son: NSObject - init (ID) {self = [super init]; if (self) {NSLog ("% @ @" NSStringFromClass ([self, class])); NSLog (@ "% @", NSStringFromClass ([super class]));} return self;} @end

First, think about what will be printed
paid more attention to my share ^_^. dry cargo


Answer: both output Son

  • Class gets the class of the caller of the current method, superClass gets the parent class of the caller of the current method, the super is just a compilation indicator, which is not a pointer to the compiler.
  • Essence: as long as the compiler sees the super flag, it will let the current object call the parent method, which is essentially the

This topic is mainly on the investigation of objc and super in the understanding of self:

  • Self is a hidden parameter of a class that points to an instance of the class that is currently called. While super is essentially a compiler identifier, and self is the same message to the point
  • When using the self method, you start looking at the list of methods in the current class, and if not, look for it from the parent class;
  • When you use super, you start looking at the parent method list. This method is then called by the parent class
  • Call [self class], will be converted into objc_msgSend function
ID objc_msgSend (ID self, SEL OP,...) - called `[super class]`, will be converted into `objc_msgSendSuper` function ID objc_msgSendSuper (struct objc_super. *super, SEL, Op,...) the first parameter is the objc_super of such a structure, which is defined as struct objc_super ID receiver __unsafe_unretained {__unsafe_unretained; Class super_class;}; first the members of receiver, similar to the above objc_msgSend parameters of self function of the first second members is the record of the current class parent class is what, tell the program to find the method from the parent class, find a way, finally inside is the use of objc_msgSend (objc_super-> receiver, @selector (class)) to call, now [self and class] call the same, so the output of the Son objc Runtime still returns the open source code - (Clas S) class method implementation - (Class) class {return object_getClass (self);}

Write in the end,
tomorrow you,
will be grateful for today’s hard work of their own!

Runtime
sit down and drink a cup of boiled water, write the sample below

expect


  • If you encounter error in the process of reading, I hope you can Issues me, thank you.
  • If you want to share something with this article, I hope you can Issues me, I would like to add more practical content for this article, thank you.
  • “The original blog”, I will continue to update, [not timing, learning experience and practical articles, is the hard truth ^_^.]
  • Thousands of handwriting, tired, look at the 3 points in the night, it is time to sleep.

Subsequent [follow-up]


I also spent time on the [
] a summary of the study summary –> GitHub (now code less, good summary to be uploaded), white boiling water ln-Blog, white ln-, white boiling water boiling water of a Book ln– WeChat public number
for –>

I’m just a thought code Porter plus my own study summary.

Attach a summary sample (Demo),

“The important part of the code has a corresponding annotation and text printing, run the program can be very intuitive performance”
“if you like or help,” can point to a Star