runtime使用之消息发送的本质

前言

  • 本章主要是描述如何简单使用runtime,runtime苹果官方是开源的,想要了解更多的朋友可以直接去看官方源码.

一, runtime简介

  • runtime简称为运行时,OC是运行时机制,比如OC的消息机制.
  • 关于C语言,我们都知道它是在编译的时候就会决定去调用哪个函数.
  • 但是,OC是在编译的时候并不能调用函数,而是在运行的时候才会真正的去根据函数名去找到并调用对应的函数的方法.
  • OC与C语言区别之一:OC是运行时机制,C语言是编译时机制.比如说:在OC中,只要你声明了函数,但是没有去实现它,在编译的时候是不会报错的,只有在运行的时候才会报错.但是,C语言只要你没有声明函数,如果直接去实现方法的话,它会在编译的时候就会报错.

二, runtime的作用

1, 发送消息
  • 众所周知, OC是消息机制,其本质就是让对象发送消息,计算机是无法读取OC语言,其本质是将OC语言通过runtime转化为C语言,最后转为二进制.
  • 使用runtime的前提是需要导入#import< objc/message.h>
    或者是#imaport< objc/runtime.h >
  • 只有对象才能发送消息,在runtime中发送消息的方法是:objc_msgSend, runtime中的方法大多都是以objc开头的.

三, runtime的使用场景

  • 使用场景1 : runtime的消息机制,自己写自己的框架
  • 使用场景2 : 如果我们想要去调用别的框架或者是系统中没有暴露出来的方法.
  • 使用场景3 : 如果我们想要研究系统内部有哪些私有方法, 有哪些私有属性.
  • 使用场景4 : 如果我们想要获取到系统自带的控件的子控件
  • 实现原理 : 根据方法名去找对应的方法实现,具体例子如下:
 // 新建一个学生类WGStudent, 在类中什么一个对象方法和类方法.
 #import <Foundation/Foundation.h>

WGStudent.h文件
@interface WGStudent : NSObject

  // - (void)study;
  // + (void)eat;

@end

WGStudent.m文件
#import "WGStudent.h"

@implementation WGStudent

- (void)study {
    NSLog(@"学习数学");
}

+ (void)eat {
    NSLog(@"吃饭");
}
@end
  • 注意 : 这里新建WGStudent类的目的主要是用于解释类的调用原理
#import "ViewController.h"
#import "WGStudent.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

//  对象发送消息
    // OC中调用对象方法
    WGStudent *student = [[WGStudent alloc] init];

    [student study];

    // [student study]的本质就是让对象发送消息
    objc_msgSend(student @selecter(study));

// 类调用对象方法,发送消息
// 调用类方法的方式:两种

    // 第一种通过类名调用
    [student eat];
    // 第二种通过类对象调用
    [[student class] eat];

    // 用类名调用类方法,底层会自动把类名转换成类对象调用
    // 本质:让类对象发送消息
    objc_msgSend([student class], @selector(eat));
}

@end

  • 特别注意 : 如果你这里就运行程序,程序会直接报错,所以这里需要做两步操作.
  • 1, 判断是否导入#import< objc/message.h> 或者 #imaport< objc/runtime.h >
  • 2, 进入工程 -> Build Settting -> msg -> No(不严格检测发送消息的调用)

四, 解析创建一个对象时,如何使用runtime转化OC的.

// 解析创建对象过程
WGStudent *student = [[WGStudent alloc] init];

// 1, 分配存储空间
    WGStudent *student = [WGStudent alloc];
--> 使用runtime创建对象
    objc_msgSend([WGStudent class], @selector(alloc));

// 2, 初始化
    student = [student init];
--> 使用runtime进行初始化
    student = objc_msgSend(student, @selector(init));

// 3, 调用对象方法
    [student study];
--> 使用runtime调用方法
    objc_msgSend(student, @selector(study));

  • 知识拓展 :

  • 1, xcode6开始,苹果不推荐我们使用runtime,把很多函数的参数注释.

  • 2, xcode6做了一些事情,导致不能调用objc_msgSend

  • 注意点:把函数名转换成某个函数指针,一定要用括号包住,在调用


    ((NSObject * (*)(id, SEL))objc_msgSend)(self,@selector(eat));
    objc_msgSend(self,@selector(eat));

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,890评论 0 9
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 6,481评论 0 9
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 9,113评论 7 64
  • 诗词歌赋篇章中曾记载“又是人间四月天,阴曹路上是何年?碑前片片飞花乱,眼底丝丝泪血煎.”谁又知唤儿声声在耳边,转身...
    城砖上的印记阅读 5,054评论 0 0
  • 九月就看到这部片子(剩者为王),没想到首映居然是我生日当天,对男神的好感又飙升了一级,上个月开始一直被朋友们提醒6...
    shally925阅读 2,312评论 0 1

友情链接更多精彩内容