The runtime has four functions: 1. To send a message 2. Method of Exchange 3. Adding methods dynamically 4. Adding attributes to the Category 5. Dictionary to model
Function One: Send Message
- The essence of a method invocation is to have the object send a message.
- Objc_msgsend, only objects can send messages, so start with OBJC.
- Use
消息机制 premise, must import #import <objc/message.h>
- Message mechanism simple to use
- CLANG-REWRITE-OBJC main.m View Final generated code
// 创建person对象 Person *p = [[Person alloc] init]; // 调用对象方法 [p eat]; // 本质:让对象发送消息 objc_msgSend(p, @selector(eat)); // 调用类方法的方式:两种 // 第一种通过类名调用 [Person eat]; // 第二种通过类对象调用 [[Person class] eat]; // 用类名调用类方法,底层会自动把类名转换成类对象调用 // 本质:让类对象发送消息 objc_msgSend([Person class], @selector(eat));
Function Two: Exchange method
- Development of the use of the scene: The system's own method is not enough, to the system's own method to extend some functions, and maintain the original function.
- Method One: Inherit the class of the system, overriding the method.
- Mode two: Use runtime, Exchange method.
@implementation viewcontroller-(void) viewdidload {[Super viewdidload]; Additional setup after loading the view, typically from a nib. Requirements: To provide functionality to the Imagenamed method, each time the picture is loaded to determine whether the tablet is loaded successfully. Step one: First make a classification, define a can load the picture and can print method + (Instancetype) Imagewithname: (NSString *) name; Step two: Exchange imagenamed and Imagewithname implementation, you can call Imagewithname, indirectly invoke the implementation of Imagewithname. UIImage *image = [UIImage imagenamed:@ "123"];} @end @implementation UIImage (Image)//load classification to memory when Call + (void) load{//Exchange method//Get Imagewithname method address methods Imagewithna me = Class_getclassmethod (self, @selector (imagewithname:)); Get Imagewithname method Address ImageName = Class_getclassmethod (self, @selector (imagenamed:)); Interchange method address, equivalent to interchange implementation mode Method_exchangeimplementations (Imagewithname, imageName);} The system method imagenamed cannot be overridden in the classification, because the function of the system will be overwritten, and the classification cannot be called super.//can both load the picture and print + (Instancetype) Imagewithname: (NSString *) name {//Call imagewithname here, equivalent to calling imagename UIImage *image = [self imagewithname:name]; if (image = = nil) { NSLog (@ "Load empty picture"); } return image; @end
Function Three: dynamic addition method
- Development Use Scenario: If a class method is very many, load the class to memory is also more expensive, need to give each method to generate a mapping table, you can use the dynamic to a class, add methods to solve.
- Classic Interview questions: There is no use of performselector, in fact, I would like to ask you have not dynamically added methods.
- Simple to use
@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. Person *p = [[Person alloc] init]; // 默认person,没有实现eat方法,可以通过performSelector调用,但是会报错。 // 动态添加方法就不会报错 [p performSelector:@selector(eat)];}@end@implementation Person// void(*)()// 默认方法都有两个隐式参数,void eat(id self,SEL sel){ NSLog(@"%@ %@",self,NSStringFromSelector(sel));}// 当一个对象调用未实现的方法,会调用这个方法处理,并且会把对应的方法列表传过来.// 刚好可以用来判断,未实现的方法是不是我们想要动态添加的方法+ (BOOL)resolveInstanceMethod:(SEL)sel{ if (sel == @selector(eat)) { // 动态添加eat方法 // 第一个参数:给哪个类添加方法 // 第二个参数:添加方法的方法编号 // 第三个参数:添加方法的函数实现(函数地址) // 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd class_addMethod(self, @selector(eat), eat, "[email protected]:"); } return [super resolveInstanceMethod:sel];}@end
Runtime effect (upper)