快速上手Runtime(一)之消息机制

Runtime简介

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

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

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

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

举个简单栗子:

NSString* testObject = [[NSData alloc] init];    testObject 在编译时和运行时分别是什么类型?

首先,声明 NSString *testObject 是告诉编译器,testObject是一个指向某个Objective-C对象的指针。因为不管指向的是什么类型的对象,一个指针所占的内存空间都是固定的,所以这里声明成任何类型的对象,最终生成的可执行代码都是没有区别的。这里限定了NSString只不过是告诉编译器,请把testObject当做一个NSString来检查,如果后面调用了非NSString的方法,会产生警告。

接着,你创建了一个NSData对象,然后把这个对象所在的内存地址保存在testObject里。那么运行时,testObject指向的内存空间就是一个NSData对象。你可以把testObject当做一个NSData对象来用。

回归正题:

我们都知道一个对象的初始化可分为两步:

1.一个对象的初始化方法分解为两步: alloc 来开辟空间,init 来初始化 :id objc = [NSObject alloc];开辟内存空间,objc = [objc init];来初始化

2.第一步初始化过程用runtime来实现:

  id objc = [NSObject alloc];  ---> id objc = objc_msgSend([NSObject class],@selector(alloc)));

  objc = [objc init]; -------> objc = objc_msgSend(objc,@selector(init));

下面看栗子:

首先定义一个Person类

#import <Foundation/Foundation.h>

@interface Person : NSObject

- (void)name;

+ (void)name;

@end



#import "Person.h"

@implementation Person

- (void)name{
    NSLog(@"对象方法---I'm doman");
}

+ (void)name{
    NSLog(@"类方法---I'm doman");

}

@end

通常情况下 我们都调用对象方法和类方法都是这样调的:

#pragma mark 如果是自己测试,请先移步Build Setting -> 搜索msg -> 设置属性为No
    
    //对象方法做法1
    Person *p1 = [[Person alloc] init];
    [p1 name];
    
    //对象方法做法2
    Person *p2 = [[Person alloc] init];
    [p2 performSelector:@selector(name)];
    // SEL:方法编号,根据方法编号就可以找到对应方法实现,此方法其实就是运用了运行时。
    
    //类方法做法1
    [Person name];
    
    //类方法做法2--通过类对象调用
    [[Person class] name];
    

其实上述方法的本质都是消息发送,那么接下来我们看用Runtime如何实现调用name方法:

1.第一步:引入Runtime框架import <objc/message.h>,注意,使用message,不使用<objc/runtime.h>的原因是message.h涵盖runtime,方法更全。

2.第二步:Build Setting -> 搜索msg -> 设置属性为No

3.使用objc_msgSend,方法;注意:只有对象才能发送消息,因此以objc开头.

    // 让person发送消息-对象方法
    Person *p3 = [[Person alloc]init];
    
    objc_msgSend(p3,@selector(name));
    
    //类方法使用runtime
    // 获取类对象
    Class personClass = [Person class];
    
    objc_msgSend(personClass, @selector(name));
    

    

调用结果:

 
Demo 地址:https://github.com/domanc/Runtime_Person.git
原文地址:https://www.cnblogs.com/dianming/p/6602537.html