Runtime的使用

简介: Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。

Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。比如:


id objc = [NSObject alloc]
objc = [objc init]


类方法本质:类对象调用[NSObject class]


id:谁发送消息

SEL: 发送什么消息


苹果运行使用objc_msgSend,如没有提示则到build setting搜索msg改为no


底层运行时会转化成发送消息


id objc = objc_msgSend(objc_getClass("NSObject"),sel_registerName("alloc"));
objc = objc_msgSend(objc,sel_registerName("init"));


最终生成消息机制,编译器做的事


最终代码,需要把当前代码重新编译,用code编译器,clang


clang -rewrite-objc 文件名


开发中runtime的使用场景:1.不得不用runtime消息机制,可以帮我们调用私有方法。2.runtime一般都是针对系统的类

方法调用流程


怎么去调用方法,对象方法:类对象的方法列表,类方法:元类中方法列表


1.通过isa指针去对应的类中查找

2.注册方法编号

3.根据方法编号去查找对应的方法

4.找到的只是最终函数实现地址,根据地址去方法去调用方法


内容五大区:栈、堆、静态区、常量区、方法区


1.栈:不需要手动管理内存,自动管理

2.堆:需要手动管理内存,自己去释放


method函数的解析


SEL selector 的简写,俗称方法选择器,实质存储的是方法的名称


IMP implement 的简写,俗称方法实现,看源码得知它就是一个函数指针


Method 对上述两者的一个包装结构.


//判断类中是否包含某个方法的实现
  BOOL class_respondsToSelector(Class cls, SEL sel)
  //获取类中的方法列表
  Method *class_copyMethodList(Class cls, unsigned int *outCount) 
  //为类添加新的方法,如果方法该方法已存在则返回NO
  BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
  //替换类中已有方法的实现,如果该方法不存在添加该方法
  IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) 
  //获取类中的某个实例方法(减号方法)
  Method class_getInstanceMethod(Class cls, SEL name)
  //获取类中的某个类方法(加号方法)
  Method class_getClassMethod(Class cls, SEL name)
  //获取类中的方法实现
  IMP class_getMethodImplementation(Class cls, SEL name)
  //获取类中的方法的实现,该方法的返回值类型为struct
  IMP class_getMethodImplementation_stret(Class cls, SEL name) 
  //获取Method中的SEL
  SEL method_getName(Method m) 
  //获取Method中的IMP
  IMP method_getImplementation(Method m)
  //获取方法的Type字符串(包含参数类型和返回值类型)
  const char *method_getTypeEncoding(Method m) 
  //获取参数个数
  unsigned int method_getNumberOfArguments(Method m)
  //获取返回值类型字符串
  char *method_copyReturnType(Method m)
  //获取方法中第n个参数的Type
  char *method_copyArgumentType(Method m, unsigned int index)
  //获取Method的描述
  struct objc_method_description *method_getDescription(Method m)
  //设置Method的IMP
  IMP method_setImplementation(Method m, IMP imp) 
  //替换Method
  void method_exchangeImplementations(Method m1, Method m2)
  //获取SEL的名称
  const char *sel_getName(SEL sel)
  //注册一个SEL
  SEL sel_registerName(const char *str)
  //判断两个SEL对象是否相同
  BOOL sel_isEqual(SEL lhs, SEL rhs) 
  //通过块创建函数指针,block的形式为^ReturnType(id self,参数,...)
  IMP imp_implementationWithBlock(id block)
  //获取IMP中的block
  id imp_getBlock(IMP anImp)
  //移出IMP中的block
  BOOL imp_removeBlock(IMP anImp)
  //调用target对象的sel方法
  id objc_msgSend(id target, SEL sel, 参数列表...)


动态添加方法class_addMethod


//resolveInstanceMethod对应的对象方法,resolveClassMethod对应的是类方法
//什么时候调用:只要一个对象调用了一个来实现的方法就就调用这个方法,进行处理
//作用:动态添加方法,处理为实现的方法
//class :给那个类添加方法
//SEL:添加那个方法
//IMP:implementation方法实现->函数->函数入口->函数名
//type:方法类型
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == NSSelecterFromString(@"run:"))
    class_addMethod(self, sel, (IMP)aaa,"v@:@");
    return YES;
}
//任何方法默认都有两个隐式参数,self,_cmd
void aaa(id self,SEL _cmd,NSNumber *num) {
    NSLog(@"跑了%@米",num);
}


TypeEncoding表


微信图片_20221018091536.png

TypeEncoding


动态添加属性


@interface NSObject (JHObject)
//@property分类:只会生成set,get方法声明,不会生成实现,也不会生成下划线成员属性
@property NSString *name;
@end
@implementation NSObject (JHObject)
-(void)setName:(NSString *)name{
    //object:给那个对象添加属性
//    key 属性名称
//    value 属性值
//    policy 保存策略
//    objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>)
    objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_COPY);
}
-(NSString *)name{
    return objc_getAssociatedObject(self, "name");
}
@end


交换方法


使用场景:当我们需要在系统方法里做事情时


示例:修改系统默认字体


//把类加载进内存的时候调用,只会调用一次
+(void)load {
//    系统方法
    Method fun1 = class_getClassMethod(self, @selector(systemFontOfSize:));
//    自定义UIFont字体类型的方法
    Method fun2 = class_getClassMethod(self, @selector(jh_systemFontOfSize:));
//    交换方法1和方法2
    method_exchangeImplementations(fun1, fun2);
}
+ (UIFont *)jh_systemFontOfSize:(CGFloat)size{
    UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:size];
    return font;
}

代码示例


相关文章
|
算法 iOS开发 UED
iOS如何进行应用的性能优化?
iOS如何进行应用的性能优化?
428 2
|
JSON 缓存 Android开发
iOS高质量的动画实现解决方案——Lottie
iOS高质量的动画实现解决方案——Lottie
1542 0
|
3月前
|
机器学习/深度学习 并行计算 测试技术
ONNX Runtime Python 推理性能优化:8 个低延迟工程实践
深度学习推理慢?未必是模型问题。本文揭示8大ONNX Runtime工程优化技巧:合理选择执行提供器、精准控制线程、规避内存拷贝、固定Shape分桶、启用图优化、CPU量化加速、预热与微批处理、向量化前后处理。不改模型也能显著提升性能,低延迟落地关键在于细节调优。
254 0
|
定位技术 API C#
.NET开源、功能强大、跨平台的图表库
.NET开源、功能强大、跨平台的图表库
343 8
|
人工智能 弹性计算 自动驾驶
2023 AI开发者生态报告:技术生态、开发范式与应用案例全景
随着人工智能技术的飞速发展,全球IT市场对AI的投入持续增长,预计到2027年将达到4236亿美元。
|
Web App开发 前端开发 iOS开发
CSS加载动画大全 126种
CSS加载动画大全是一个css Loaders加载动画特效汇总,一共包含126种加载动画效果,不同样式不同图案,简单实用,一览包含所有,会让你在等待的过程中,体验视觉盛宴,给用户不一般的加载体验,欢迎下载试试!代码适用浏览器:搜狗、360、FireFox(建议)、Chrome、Safari、Opera、傲游、世界之窗,是一款不错的的特效插件,希望大家喜欢!
338 2
|
算法 数据可视化 新制造
Threejs路径规划_基于A*算法案例完整版
这篇文章详细介绍了如何在Three.js中完整实现基于A*算法的路径规划案例,包括网格构建、路径寻找算法的实现以及路径可视化展示等方面的内容。
614 0
Threejs路径规划_基于A*算法案例完整版
|
机器学习/深度学习 存储 人工智能
人工智能在医疗诊断中的应用:挑战与前景
在现代医疗领域,人工智能(AI)技术正逐步改变传统诊断方式。本文探讨了AI在医疗诊断中的应用,包括影像分析、预测模型和数据整合等方面。同时,文章深入分析了AI应用过程中面临的挑战,如数据隐私、伦理问题和技术壁垒,最后展望了未来AI在医疗领域的潜力和可能的发展方向。
602 27
|
小程序 定位技术 开发工具
【微信小程序-原生开发+TDesign】通用功能页封装——地点搜索(含腾讯地图开发key 的申请方法)
【微信小程序-原生开发+TDesign】通用功能页封装——地点搜索(含腾讯地图开发key 的申请方法)
422 0

热门文章

最新文章