美文网首页
runtime应用场景

runtime应用场景

作者: Arackboss | 来源:发表于2017-05-31 16:27 被阅读0次
    • 场景1 ----------- runtime 发送消息 -----------
      • objc/msgSend 只有对象才能发送消息,因此以objc开头
      • 导入 #import <objc/message.h> 或者直接导入 #import <objc/runtime.h>
      • 注意 Xcode 6 之后代码检查 单独使用<objc/message.h>会报错
      • builtSeting 修改 Enable Strict Checking of objc_msgSend Calls -> NO 才能调用 objc_msgSend `

    我们创建一个对象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],发什么消息.

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

    案例:这里我们写一个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"];

    相关文章

      网友评论

          本文标题:runtime应用场景

          本文链接:https://www.haomeiwen.com/subject/vcorfxtx.html