Friends who do iOS know or hear about itruntime, This thing looks very similarjavabut its function is much better thanjavareflection. passruntimeWe can dynamically enter a classAdd properties, member variables, methods, and read and write access to it.
1. Introduction to runtime
RunTime is referred to as runtime. OC isRuntime mechanism, that is, some mechanisms at runtime, the most important of which is the message mechanism.
For C language,When the function is called, it will determine which function to call.。
For OC functions,Dynamic call process, it cannot decide which function to call when compiled, only when it is actually run will be based on the name of the function
Find the corresponding function to call.
It turns out:
During the compilation stage, OC canCall any function, even if this function is not implemented, there will be no error as long as it has been declared.
During the compilation stage, C language callsUnimplemented functionsAn error will be reported.
2. Runtime function
1. Send a message
The essence of method calls is to let the object send messages.
objc_msgSend,
Only objects can send messages, so they start with objc.
Before using the message mechanism, you must import#import <objc/>
Simple use of message mechanism
The principle of message mechanism: the object is based on the method number SEL to find the corresponding method implementation
// Create a person object Person *p = [[Person alloc] init]; // Call object method [p eat]; // SEL: Method number, you can find the corresponding method implementation according to the method number [p performSelector:@selector(eat)]; // Essence: Let the object send a message objc_msgSend(p, @selector(eat)); // Call class methods: two ways // The first type converts the essential class name into a class object by calling the class name [Person eat]; // The second type is called through class object [[Person class] eat]; [personClass performSelector:@selector(eat)]; // Call the class method with a class name, the underlying layer will automatically convert the class name into a class object call // Essence: Let the class object send a message objc_msgSend([Person class], @selector(eat));
2. Exchange method
Development and usage scenarios: The system's own methods are not functional enough. Expand some functions for the system's own methods and maintain the original functions.
Method 1:Inherit the system's classes and override the methods.
Method 2:Use runtime, exchange methods.
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // Requirements: Provide functions for the imageNamed method, and determine whether the image is loaded successfully every time the image is loaded. // Step 1: First create a classification and define a method that can load images and print them + (UIImage *)xmg_imageNamed:(NSString *)imageName; // Step 2: Exchange the implementation of imageNamed and xmg_imageNamed, and you can call xmg_imageNamed and indirectly call the implementation of xmg_imageNamed. UIImage *image = [UIImage imageNamed:@"123"]; imageNamed: Implementation method:Underlying callPH_imageNamed nature:Implementation of two methods of exchangeimageNamedandPH_imageNamedmethod CallimageNamed其实就是CallPH_imageNamed imageNamedLoading pictures,I don't know if the image is loading successfully 以后CallimageNamedWhen,You will know if the picture is loading } @end @implementation UIImage (Image) // Called when loading the classification into memory+ (void)load { // Implementation of exchange methods, methods are defined in the class // class_getMethodImplementation: Get method implementation // class_getInstanceMethod: Get the object // class_getClassMethod: Get class method // IMP: Method implementation // imageNamed // Class: Which class method to get // SEL: Get the method number, and you can find the method according to the SEL Method imageNameMethod = class_getClassMethod([UIImage class], @selector(imageNamed:)); Method PH_imageNameMethod = class_getClassMethod([UIImage class], @selector(PH_imageNamed:)); // Implementation of exchange method method_exchangeImplementations(imageNameMethod, PH_imageNameMethod); } } // You cannot rewrite the system method imageNamed in the classification because it will overwrite the system's functions, and super cannot be called in the classification. // Can load pictures and print+ (UIImage *)PH_imageNamed:(NSString *)imageName { // Load the picture UIImage *image = [UIImage PH_imageNamed:imageName]; // 2. Judgment function if (image == nil) { NSLog(@"Loading empty"); } return image; } @end
3. Dynamic addition method
Development usage scenarios: If there are many methods for a class and it is more resource-consuming when loading the class into memory, and you need to generate a mapping table for each method, you can use dynamically to add methods to solve the problem.
Simple use
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. Person *p = [[Person alloc] init]; // The default person does not implement the eat method. You can call it through performSelector, but an error will be reported. // Dynamically add methods will not report errors [p performSelector:@selector(eat)]; } @end @implementation Person // void(*)() // The default method has two implicit parameters.By default, one method has two parameters,self,_cmd,Implicit parameters self:Method caller _cmd:The number of the call method void eat(id self,SEL sel) { NSLog(@"%@ %@",self,NSStringFromSelector(sel)); } // When an object calls an unimplemented method, this method will be called to process and the corresponding method list will be passed over.// It just happens to be used to determine whether the unimplemented method is the method we want to add dynamically <!--Dynamic addition method,Implement this firstresolveInstanceMethod--> <!-- resolveInstanceMethodCall:当Call了没有实现的方法没有实现就会CallresolveInstanceMethod--> <!-- resolveInstanceMethodeffect:You know which methods are not implemented,从而Dynamic addition method--> <!-- sel:No implementation method--> + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(eat)) { // Dynamically add eat method // First parameter: Which class to add a method // The second parameter: method number of the method added // The third parameter: function implementation of the method (function address) // The fourth parameter: the type of the function, (return value + parameter type) v:void @: object->self: means SEL->_cmd class_addMethod(self, @selector(eat), eat, "v@:"); } return [super resolveInstanceMethod:sel]; } @end
4. Add attributes to the classification
Principle: Declaring properties to a class is actually essentially adding associations to this class, not directly adding the memory space of this value to the class memory space.
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // Dynamically add attribute name to the system NSObject class NSObject *objc = [[NSObject alloc] init]; = @"abc"; NSLog(@"%@",); } @end // Define the associated keystatic const char *key = "name"; - (void)setName:(NSString *)name { // Add properties and objects // Create an association to an object and add attributes // object: Which object to add attributes // key: attribute name, obtain the associated object according to key, void * == id // value: the associated value // policy: policy objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSString *)name { return objc_getAssociatedObject(self, @"name"); }
The above is a summary of the use of runtime in iOS. This article mainly summarizes the principles and usage. Runtime has very powerful functions and requires friends to learn and research more. Hope this article will be helpful to everyone.