runtime应用场景

  • 场景1 ----------- runtime 发送消息 -----------
    • objc/msgSend 只有对象才能发送消息,因此以objc开头
    • 导入 #import 或者直接导入 #import
    • 注意 Xcode 6 之后代码检查 单独使用会报错
    • builtSeting 修改 Enable Strict Checking of objc_msgSend Calls -> NO 才能调用 objc_msgSend `

我们创建一个对象Dog 自定义一个实例方法和类方法,并实现方法:

#import 

@interface Dog : NSObject

-(void)run;

+(void)eat;

@end

#import "Dog.h"

@implementation Dog

-(void)run
{
    NSLog(@"一只狗正在奔跑");
}

+(void)eat
{
    NSLog(@"一只狗正在吃。。。");
}

@end

然后我们在vc里面使用

// 创建对象 -> 调用方法
Dog *d = [[Dog alloc] init];
// 调用方法 -> 实例方法
[d run];
// 系统底层本质 -> 让对象发消息
objc_msgSend(d, @selector(run)); // 等同于 [d run];
// 调用方法 -> 类方法
[Dog eat];
objc_msgSend([Dog class], @selector(eat)); // 等同于 [Dog eat];

消息机制原理:
对象根据方法编号SEL去映射表查找对应方法的实现,即我们在调用实例方法的时候,其实是实例对象d,在发送消息,消息的实现,其实是SEL,根据方法编号,去映射表查找对应方法的实现.类方法本质是[Dog class],发什么消息.

  • 场景2 ----------- runtime 交换方法 -----------
    使用场景,系统自带方法功能不够用,给系统自带的方法扩展一些功能,并保存原有功能:
    • 实现方法 1 -> 继承系统的类, 重写方法.
    • 实现方法 2 -> runtime 交换方法

案例:这里我们写一个UIImage的类目,来保证UIImage,不会被渲染,同时,如果图片为空,会打印提示.

#import 

@interface UIImage (Image)

// 创建一个类方法

// 传入 一个字符串 -> 返回 不被 渲染的原始图片

+ (id)ImageOriginalWithStrName:(NSString *)name;
@end

在.m进行实现, 使用method_exchangeImplementations(method1, method2)方法交换,详情看代码注释.


#import "UIImage+image.h"
#import 

@implementation UIImage (image)
+(void)load
{
    //获取方法
    Method imageWithName = class_getClassMethod(self, @selector(imageOriginaWithStrName:));
    
    Method imageName = class_getClassMethod(self, @selector(imageNamed:));
    
    //交换方法
    method_exchangeImplementations(imageWithName, imageName);
}

+(id)imageOriginaWithStrName:(NSString *)name
{
    UIImage *image = [[self imageOriginaWithStrName:name] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    if (image == nil) {
        NSLog(@"加载图片为空");
    }
    
    return image;
}
@end

在vc中使用 :
UIImage *image = [UIImage imageNamed:@"123"];

你可能感兴趣的:(runtime应用场景)