35.runtime(消息机制)

一.runtime简介

  • Runtime简称运行时,OC就是运行时机制,也就是在运行的时候的一些机制,其中最主要的是消息机制.

  • 对于C语言,函数的调用在编译的时候会决定调用哪个函数.

  • 对于oc的函数,属于动态调用过程,在编译的时候并不能真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用.

  • 事实证明:

  • (1).在编译阶段,oc可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错.

  • (2).在编译阶段,c语言调用未实现的函数就会报错

OC:运行时机制,消息机制是运行时机制最重要的机制
消息机制:任何方法调用,本质都是发送消息

二.runtime的使用

运行时,发送消息,谁做事请就拿谁
xcode5 之后,苹果不建议使用底层的方法
** xcode5之后,使用运行时**(使用运行时的原因)

(1).方法调用的本质,就是让对象发送消息.objc_msgSend只有对象才能发消息,因此以objc开头,使用消息机制前提,必须导入#import

(2).Build Setting -> 搜索msg -> 设置属性为NO

35.runtime(消息机制)_第1张图片
运行时

(3).真正的使用

在外面我定义了一个Person的类,方法都进行了实现

35.runtime(消息机制)_第2张图片
Person

消息机制调用对象方法:(调用的是多个参数的)

 objc_msgSend(person, @selector(run:sdd:),25,@"名字");

额外提一句:类方法的调用:本质是把类名转化为类对象

//类方法的调用:本质是把类名转化为类对象
1.[Person eat];
2.[[Person class]performSelector:@selector(eat)];
3.
id personClass = [Person class];
[personClass performSelector:@selector(eat)];

类方法运行机制的调用:

objc_msgSend([Person class], @selector(eat));

如果用一张图来表示的话就是下面的:

35.runtime(消息机制)_第3张图片
**运行时调用机制**

1.先用对象 -> 2.performSelector -> 3.@selector(方法:类似键)+有参数就添加 ->
4.这个对象的方法库里面寻找方法 -> 5.找到这个方法来调用

三.runtime交换方法

UIImage+Image.h
#import
@interface UIImage (Image)

+(__kindof UIImage *) jk_imageNamed:(NSString *)imageName;

@end

UIImage+Image.m
#import "UIImage+Image.h"
#import
@implementation UIImage (Image)
//交换的方法实现,方法都定义在类里面

/**
 *  Class : 获取哪个类方法
 *  SEL : 获取方法编号,根据SEL就能去对应的类找方法
 */

//获取类方法
//class_getClassMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)

//获取对象方法
//class_getInstanceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)

+(void)load
{
//交换方法实现

//获取类方法
Method imageMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));

Method jk_imageMethod = class_getClassMethod([UIImage class], @selector(jk_imageNamed:));

method_exchangeImplementations(imageMethod, jk_imageMethod);

}

+(UIImage *)jk_imageNamed:(NSString *)imageName
{
   UIImage *image = [UIImage jk_imageNamed:imageName];

   if (image == nil) {
    
      NSLog(@"图片为空");
    }else
    {

       NSLog(@"图片不为空");
    }
  return image;
}

四.runtime动态添加方法(这里添加的是带参数的方法)

在此定义的是一个Son方法

//
//  Son.m
//  OC的runtime

#import "Son.h"
#import 
@implementation Son

//定义函数
void eat(id self,SEL _cmd,id patam1)
{
/**
 *  系统默认会传方法
 *
 */
NSLog(@"调用eat %@ %@ %@",self,NSStringFromSelector(_cmd),patam1);

}

//默认一个方法有两个参数,self,_cmd
//self:方法的调用者
//_cmd:调用方法的编号

//动态添加方法,首先实现这个(没有实现的方法会走这里)
+(BOOL) resolveInstanceMethod:(SEL)sel
{

//动态添加eat方法

/**
 *  对象方法的方法添加解释
 *
 *  @param cls#>    给那个类添加方法
 *  @param SEL#>    添加方法的方法编号
 *  @param imp#>    方法实现,函数入口,函数名
 *  @param types#>  方法类型
 *
 */
// class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>)

    if ([NSStringFromSelector(sel) isEqualToString:@"eat:"])
    {
    
       // @:对象 : SEL
       class_addMethod(self, sel, (IMP)eat, "v@:@");
    
        return YES;
     }

     return [super resolveInstanceMethod:sel];
}
@end

五.runtime动态添加属性

给一个类动态的添加属性

我写了一个NSObject+shuxing.h类

NSObject+shuxing.h
生命一个属性

 @property(nonatomic,strong) NSString *name;

NSObject+shuxing.m

#import "NSObject+shuxing.h"
#import 

@implementation NSObject (shuxing)

-(void)setName:(NSString *)name
{
//添加属性与对象有关
//给某个对象产生关联
/**
 *  id object  给哪个对象添加属性
 *  const void *key 属性名,根据key去获取关联的对象  void * == id
 *  id value  关联的值
 *  objc_AssociationPolicy policy  策略,用什么策略去保存
 */
 objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}
-(NSString *)name
{
   return objc_getAssociatedObject(self, @"name");
}
@end

runtime部分代码 密码: kd5y

你可能感兴趣的:(35.runtime(消息机制))