runtime

runtime简介 

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

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

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

4.在编译阶段,OC可以调用任何函数,即使这个函数并未被实现,只要声明过就不会报错。而C语言调用未实现的函数就会报错。

1.消息发送机制

#import <objc/message.h>

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

//    [p eat];

    objc_msgSend(p, sel_registerName("eat"));

    /*

     方法的调用流程:

     对象方法: 从他的类对象的方法类表里去找。

     类方法: 从他的元类的方法类表里去找。

     objc_class *Class.每个类都是一个结构体指针

     Class 里面有个isa指针,指向其元类。

     NSObjectisa指针,指向自己。而他的super class nil

     */

通过验证 : [p eat] 最终会转化成 objc_msgSend (p,  sel_registerName ( "eat" )) 。
通过objc_msgSend()可以调用未声明的方法,即使eat方法没有在Person.h类中声明,只有.m的实现也是可以调用的。

2. 方法替换

例子 :替换 imageNamed:系统方法的实现。

#import "UIImage+myImage.h"

#import <objc/message.h>


@implementation UIImage (myImage)

// +(void)load 在程序运行的时候就已经加到内存里了。

+(void)load{

    Method wl_ImageNamedMethod = class_getClassMethod(self, @selector(wl_ImageNamed:));

    

    Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));

    

    method_exchangeImplementations(wl_ImageNamedMethod, imageNamedMethod);

}


+(UIImage *)wl_ImageNamed:(NSString *)name{

    UIImage *image = [UIImage wl_ImageNamed:name];//注意 : 因为交换了wl_ImageNamed 和 imageNamed 的实现,所以在wl_ImageNamed的实现中再调用imageNamed等于再一次去实现 wl_ImageNamed,如此反反复复,最终导致线程程序崩溃。

    if (image) {

        NSLog(@"加载成功");

    }else{

        NSLog(@"加载失败");

    }

    return image;

}

3.动态添加属性

@interface Person : NSObject

@property (nonatomic , strong) NSString *name;

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

    NSString *str = [NSString stringWithString:@"123"];//这是一个字符串对象。

    p.name =str; //属性赋值

属性赋值的本质就是让属性去关联某个对象。

例子:给系统的类NSObject 添加字符串类型的name属性

.h

@interface NSObject (property)

@property NSString *name;

.m

#import "NSObject+property.h"

#import <objc/message.h>

@implementation NSObject (property)

-(void)setName:(NSString *)name{

    //<#id object#> 给哪个类添加属性

    //<#const void *key#> 属性名称-->标记

    objc_setAssociatedObject(self, "myName", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

-(NSString *)name{

    return objc_getAssociatedObject(self, "myName");

}

4.动态添加方法

一个Personl类的对象 p 去调用一个eat方法。

[p eat]也可以这么去描述 [p performSelector:@selector(eat)].如果这个eat的方法没有实现,程序就会崩溃,那么需要动态地去添加eat的方法的实现防止程序崩溃。

runtime 提供了一个解决方法 :

//+(BOOL)resolveInstanceMethod:(SEL)sel

#import "Person.h"

#import <objc/message.h>

@implementation Person


//id self , SEL _cmd 是两个隐藏参数,如果不添加,在eat方法中是无法使用 self这个参数的。

void eat(id self , SEL _cmd , NSString * str){

    NSLog(@"吃饭了---%@",str);

}


+(BOOL)resolveInstanceMethod:(SEL)sel{

    NSLog(@"来了");

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

        /*

         Class : 给哪个类添加方法

         SEL : 方法名

         IMP : 函数名 --->函数的实现

         types : 类型--->参数类型

         */

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

        return YES;

    }

    return [super resolveInstanceMethod:sel];

}

API文档中对于 types 的解释:

Table 6-1  Objective-C type encodings

Code

Meaning

c

A char

i

An int

s

A short

l

A long

l is treated as a 32-bit quantity on 64-bit programs.

q

A long long

C

An unsigned char

I

An unsigned int

S

An unsigned short

L

An unsigned long

Q

An unsigned long long

f

A float

d

A double

B

A C++ bool or a C99 _Bool

v

A void

*

A character string (char *)

@

An object (whether statically typed or typed id)

#

A class object (Class)

:

A method selector (SEL)

[array type]

An array

{name=type...}

A structure

(name=type...)

A union

bnum

A bit field of num bits

^type

A pointer to type

?

An unknown type (among other things, this code is used for function pointers)




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七尺天涯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值