runtime应用场景

2017-05-31  本文已影响0人  Arackboss

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

#import <Foundation/Foundation.h>

@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],发什么消息.

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

#import <UIKit/UIKit.h>

@interface UIImage (Image)

// 创建一个类方法

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

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

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


#import "UIImage+image.h"
#import <objc/runtime.h>

@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"];

上一篇下一篇

猜你喜欢

热点阅读