概述

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

调用runtimeAPI需要导入都文件#import <objc/runtime.h>

常用的runtime函数

// 获取一个类的Class类型(类对象)
objc_getClass(const char * _Nonnull name) // 获取函数的IMP
class_getMethodImplementation(Class cls, SEL name) // 获取对象某个方法
Method method = class_getInstanceMethod(Class cls, SEL name) // 获取类的某个方法
Method method = class_getClassMethod(Class cls, SEL name); // 交换方法
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) // 动态给类添加方法
class_addMethod(Class cls, SEL name, IMP imp, const char * types); // 获取类的成员
class_copyIvarList(Class cls, unsigned int * outCount);

runtime使用场景

利用类扩展给对象添加属性

在类扩展中给类添加属性,默认只会生成属性的getter与setter方法声明,不会生成方法实现和带下划线成员变量

示例: 给UIView添加一个NSDictinonary和flag属性 ,flag为BooL类型,作为基本类型属性的代表

#import <UIKit/UIKit.h>

@interface UIView (Example)

// 动态添加基本数据类型成员变量
@property (nonatomic, assign) BOOL flag; // 动态添加对象类型成员变量
@property (nonatomic, strong) NSDictionary *dict;
@end #import "UIView+Example.h"
#import <objc/runtime.h> @implementation UIView (Example)
/***************************动态添加基本数据类型成员变量***************************/
- (void)setFlag:(BOOL)flag
{
// 注意:参数二 需要传递一个key 这里建议用@selector(属性名),不用定义很多常量
objc_setAssociatedObject(self, @selector(flag), @(flag), OBJC_ASSOCIATION_ASSIGN);
} - (BOOL)flag
{
id object = objc_getAssociatedObject(self, @selector(flag));
return object?[object boolValue]: NO;
} /***************************动态添加对象类型成员变量***************************/
-(void)setDict:(NSDictionary *)dict
{
objc_setAssociatedObject(self, @selector(dict), dict, OBJC_ASSOCIATION_RETAIN);
} - (NSDictionary *)dict
{
return objc_getAssociatedObject(self, @selector(dict));
}
@end

动态添加方法

class_addMethod(Class  _Nullable cls, SEL name, IMP  imp, const char * types);

第一个参数:类对象 可以通过objc_getClass获取 第二个参数 动态添加的方法SEL

第三个参数 方法或者函数的实现地址 class_getMethodImplementation 方法实现

第四个参数:描述方法/函数的返回值类型、参数类型 使用@encode()可获得类型的编码

下面示例给ViewController添加一个addNewMethod:方法,然后通过performSelector 在程序运行时调用该方法。

// 动态添加的方法
- (void)addNewMethod:(UIButton *)button
{
NSLog(@"-------------------%@", button);
} - (void)viewDidLoad {
[super viewDidLoad]; // 1.获取动态添加方法的地址IMP
IMP addNewMethodIMP = class_getMethodImplementation([self class], @selector(addNewMethod:)); // 2.获取方法的types
char types[100];
strcpy(types, @encode(void)); // 返回值类型
strcpy(types, @encode(id)); // 每个函数自带的id self参数
strcpy(types, @encode(SEL)); // 每个函数自带的SEL sel参数
strcpy(types, @encode(UIButton)); // 动态添加方法addNewMethod的button参数 // 3.动态绑定添加方法
class_addMethod(objc_getClass("ViewController"), @selector(addNewMethod:), addNewMethodIMP, types);
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 通过performSelector调用函数
[self performSelector:@selector(addNewMethod:) withObject:UIButton.new];
}

方法交换

程序在启动是会加载开发者编写的类,在方法的调用时动态的去查找方法的实现。如果实现方法交换的思路时在程序加载时交换方法的实现。

iOS开发系列-Runtime运用场景的更多相关文章

  1. iOS开发系列--Swift进阶

    概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...

  2. iOS开发系列--通知与消息机制

    概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...

  3. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

  4. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

  5. IOS开发系列 --- 核心动画

    原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...

  6. iOS开发系列

    因为最近面试了一些人,校招.初中级.高级.架构师,各种级别的,发现大家水平差异很大,有的高级的工程师很多问题都回答不上来,所以想梳理下iOS的知识点,写成一个系列,如果时间允许的话,会录制成视频放到网 ...

  7. iOS开发系列--让你的应用“动”起来【转载】

    概览 原文链接:http://www.cnblogs.com/kenshincui/p/3972100.html 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...

  8. iOS开发系列--通知与消息机制--转

    来自:http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户 ...

  9. iOS开发系列之app的一天

    本文主要讲述我对 iOS 开发的一些理解,希望能通过 app 从启动到退出,将一些的知识整合起来,形成一条知识链,目前涉及到的知识点有 runloop.runtime.文件存储.界面布局.离线推送.内 ...

随机推荐

  1. QinQ 技术解析

    目录 1. 概述 2. QinQ 的产生背景 3. QinQ的作用及原理 4. QinQ 技术的优点 5. QinQ 的报文结构 6. QinQ的实现方式 (1) 基本QinQ (2) 灵活QinQ ...

  2. 提取json对象中的数据,转化为数组

    var xx1 = ["乐谱中的调号为( )调", "写出a自然小调音阶.", "以G为冠音,构写增四.减五音程.", "调式分析 ...

  3. Day 21 python :面向对象 类的相关内置函数 /单例模式 /描述符

    1.isinstance(obj,cls) 检查obj是否是类cls的对象: 备注:用isinstance 的时候,产生实例后,会显示实例既是父类的实例,也是子类的实例 class Mom: gend ...

  4. 1-Navicat无法远程连接Ubuntu上的MySQL(已解决)

    转发自: https://jingyan.baidu.com/article/4d58d54156ff069dd4e9c085.html

  5. LCA的RMQ求法

    参考博客 仔细想一想:最近的公共祖先,其实,搜索时回朔,连通这两点,那深度最低肯定是最近的公共祖先啊. 那这样就可以变成RMQ问题了. #include<stdio.h> #include ...

  6. POJ 2135 /// 最小费用流最大流 非负花费 BellmanFord模板

    题目大意: 给定一个n个点m条边的无向图 求从点1去点n再从点n回点1的不重叠(同一条边不能走两次)的最短路 挑战P239 求去和回的两条最短路很难保证不重叠 直接当做是由1去n的两条不重叠的最短路 ...

  7. zabbix--监控的组件和进程介绍

    上图是zabbix的架构,zabbix proxy(代理),可以减小IO并发. zabbix web GUI是用php写的画图工具,从数据库抓取数据. zabbix database zabbix获取 ...

  8. 关于使用AWS的centos

    AWS的centos在版本上有些许不同. 当使用6代的时候,默认的登录用户是root 使用7代的系统,默认的登录用户是centos 否则登录不上去

  9. wp api jwt 403 (Forbidden) -- JWT is not configurated properly, please contact the admin

    需要在 wp-config.php 文件中配置 define('JWT_AUTH_SECRET_KEY', 'your-top-secrect-key'); 參考 403 (Forbidden) -- ...

  10. python 模拟按键模拟键盘按键按下放开

    python模拟按键 pip install pypiwin32安装库 import win32conimport win32apiimport time 导入 打个比方模拟A win32api.ke ...