The method substitution, can replace any external class's method, but the dynamic addition method can only implement in the object which the added class creates, but uses the method substitution and the dynamic addition method to use, may implement, the arbitrary external class dynamically adds the necessary method, this method may be the class method also may be the instance method, This external class can also be a class that does not have any method declarations and implementations.
Main idea: Using the run-time method to replace will be in the external class will be the custom method hy_resolveInstanceMethod
or hy_resolveClassMethod
(with the hy_
prefix is my custom method) and need to be added in the class resolveInstanceMethod
or resolveClassMethod
method substitution, replace before hy_resolveInstanceMethod
or hy_resolveClassMethod
inside the method is written in the resolveInstanceMethod
or the resolveClassMethod
logic of how the runtime dynamically adds the method is written internally.
A bit around, but at least need to continue to read the source code, thinking about the logic, in fact, is not difficult, the premise is familiar with the use of the runtime method.
Defects: 1, the method with parameters is difficult to handle, parameter values need to be based on the actual business logic.
Before use
import <objc/message.h>
, need following:
Create Person.h and PERSON.M
Person.h:
1 #import <Foundation/Foundation.h>23@interface person:nsobject 4 5 @end
person.m:
1 #import " Person.h " 2 3 @implementation Person 4 5 @end
Create OtherPerson.h and OTHERPERSON.M
OtherPerson.h:
1 #import <Foundation/Foundation.h>23@interface otherperson:nsobject 456@end
OTHERPERSON.M:
1 //2 //Created by Heyang on 16/1/11.3 //copyright©2016 year Heyang. All rights reserved.4 //5 6 #import "OtherPerson.h"7 #import<objc/message.h>8 9 @implementationOtherpersonTen One A+(void) load{ -Class clazz = nsclassfromstring (@" Person"); - the //gets the class method before the substitution -Method instance_eat = - Class_getclassmethod (Clazz, @selector (resolveinstancemethod:)); - //get the Substituted class method +Method instance_noteat = - Class_getclassmethod (Self, @selector (hy_resolveinstancemethod:)); + A //then the Exchange class method at method_exchangeimplementations (Instance_eat, instance_noteat); - - //gets the class method before the substitution -Method class_eat = - Class_getclassmethod (Clazz, @selector (resolveclassmethod:)); - //get the Substituted class method inMethod class_noteat = - Class_getclassmethod (Self, @selector (hy2_resolveclassmethod:)); to + //then the Exchange class method - method_exchangeimplementations (Class_eat, class_noteat); the * } $ Panax Notoginseng voidEat_1 (IDSelf,sel SEL) - { theNSLog (@"We 're not eating anymore."); +NSLog (@"%@ %@", Self,nsstringfromselector (SEL)); A } the voidEat_2 (IDSelf,sel SEL, nsstring* str1,nsstring*str2) + { -NSLog (@"We 're not eating anymore."); $NSLog (@"%@ %@", Self,nsstringfromselector (SEL)); $NSLog (@"print two parameter values:%@ and%@", STR1,STR2); - } - the -+(BOOL) Hy_resolveinstancemethod: (SEL) sel{Wuyi //when SEL is a eat method in the implementation method the if(sel = = nsselectorfromstring (@"Eat")) { - //adding eat methods on the fly Wu - //first argument: which class to add a method to About //Second parameter: Method number for adding a method $ //Third parameter: Add a function implementation of a method (function address) - //The fourth parameter: the type of the function, (return value + parameter type) v:void @: Object->self: Represents Sel->_cmd -Class_addmethod (Self, SEL, (IMP) eat_1,"[email protected]:"); - } A returnYES; + } the+(BOOL) Hy2_resolveclassmethod: (SEL) sel{ - $ if(sel = = nsselectorfromstring (@"Eat:with:")) { the theClass_addmethod (Objc_getmetaclass (" Person"), SEL, (IMP) eat_2,"v#:@@"); the } the - returnYES; in } the the @end
Last in file ' main.m ':
MAIN.M:
1 /**2 *3 * Swap method and dynamic Add method (Exchange methods and dynamically add methods)4 *5 */6 7 #import<Foundation/Foundation.h>8 9 //ignore undeclared warm ignores undeclared warningsTen #pragmaClang Diagnostic push One #pragmaClang diagnostic ignored "-wundeclared-selector" A - intMainintargcConst Char*argv[]) { - @autoreleasepool { the //get this person class gets the person category -Class clazz = nsclassfromstring (@" Person"); - //get this person Instance get the person instance - IDperson =[[Clazz alloc] init]; + - //send message to ' eat ' method in person Class or person Instance + //the ' eat ' method that sends a message to the person class or person instance does not contain parameters A [Person Performselector: @selector (Eat) withobject:nil]; at //the ' eat ' method that sends a message to the person class contains two parameters - [Clazz performselector: @selector (eat:with:) -Withobject:@"Hello" -Withobject:@" World"]; - } - return 0; in } - to #pragmaClang Diagnostic Pop
The Code test result
Extra
Download
Download GitHub Code Source
Runtime method substitution and dynamic Add instance method combined with