iOS Runtime总结(一)

一、runtime简介

*RunTime简称运行时。OC就是`运行时机制`,也就是在运行时候的一些机制,其中最主要的是消息机制。

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

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

*事实证明:

*在编译阶段,OC可以`调用任何函数`,即使这个函数并未实现,只要声明过就不会报错。

*在编译阶段,C语言调用`未实现的函数`就会报错。

二、runtime作用

1.发送消息

*方法调用的本质,就是让对象发送消息。

* objc_msgSend,只有对象才能发送消息,因此以objc开头.

* 使用`消息机制`前提,必须导入#import <objc/message.h>

*消息机制简单使用

三 编写程序

1.首先导入头文件:

使用运行时的第一步:导入<objc/message.h>

第二步:Build Setting ->搜索msg ->设置属性为No,否则会报错。

2.程序

    // 创建person对象

    Person *p = [[Person alloc] init];

    

    // 调用对象方法

    [p run];    

    

    // 本质:让对象发送消息

    objc_msgSend(p, @selector(run));


    // 调用类方法的方式:两种

    // 第一种通过类名调用

    [Person run];

    // 第二种通过类对象调用

    [[Person class] run];

    

    // 用类名调用类方法,底层会自动把类名转换成类对象调用

    // 本质:让类对象发送消息

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

3.消息机制原理:



4.交换方法

*开发使用场景:系统自带的方法功能不够,给系统自带的方法扩展一些功能,并且保持原有的功能。

*方式一:继承系统的类,重写方法.

* 方式二:使用runtime,交换方法.


5.交换ImageNamed:方法,系统提供的方法是不允许为空值,如果为空值就会导致奔溃。
 补充,添加一个分类方法,UIImage (Image),通过load方法提前修改。
+load和+initial 方法,load会在一加载就执行,而initial方法需要调用才会执行。


#import "UIImage+Image.h"

#import <objc/message.h>


@implementation UIImage (Image)


+(void)load{

        Method imageNameMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));

        

        Method wcyImageNamedMethod = class_getClassMethod([UIImage class], @selector(wcyimageNamed:));

        

        // 交换方法实现

        method_exchangeImplementations(imageNameMethod, wcyImageNamedMethod);

}


// 不能在分类中重写系统方法imageNamed,因为会把系统的功能给覆盖掉,而且分类中不能调用super.


+ (UIImage *)wcyimageNamed:(NSString *)imageName{

        // 1.加载图片

        UIImage *image = [UIImagewcyimageNamed:imageName];

        

        // 2.判断功能

        if (image == nil) {

                NSLog(@"加载image为空");

        }

        

        return image;

}


     self.image = [UIImageimageNamed:@""];

        NSLog(@"%@",self.image);

控制台输出:

2016-08-06 23:08:30.821 huidiao_exercise[88640:647609] 加载image为空。


6.动态添加方法 : 有没有使用performSelector,其实就是动态添加过方法。

* 开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。

* 简单使用

//动态添加方法

Person 类中:

void addMethods(idself,SEL _cmd,id param1){

         NSLog(@"调用eat %@ %@ %@",self,NSStringFromSelector(_cmd),param1);

}


+(BOOL)resolveInstanceMethod:(SEL)sel{

        

        if (sel == @selector(eat:)) {


        // 动态添加eat方法

        

        // 第一个参数:给哪个类添加方法

        // 第二个参数:添加方法的方法编号

        // 第三个参数:添加方法的函数实现(函数地址)

        // 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd

                class_addMethod(self,@selector(eat:), (IMP)addMethods,"v@:@");

                return YES;

        }

        

        return [super resolveInstanceMethod:sel];

        

        

        

}


调用

    Person *p = [[Personalloc]init];

    // 动态添加方法

//    [p performSelector:@selector(eat)];

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Wundeclared-selector"

        [p1 performSelector:@selector(eat:)withObject:@"hello world"];

#pragma  clang diagnostic pop


2016-08-06 23:31:02.718 huidiao_exercise[89937:664758] 调用eat <Person: 0x7fb860419c80> eat: hello world






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值