概述

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. 2. Pycharm的介绍与使用

    使用Python原生IDLE IDLE是Python软件包自带的一个集成开发环境,点击开始-->Python安装包-->IDLE.启动 IDLE 时,会显示>>>,可以在 ...

  2. MyBatis-Spring(二)--SqlSessionTemplate实现增删改查

    SqlSessionTemplate是个线称安全的类,每运行一个SqlSessionTemplate时,它就会重新获取一个新的SqlSession,所以每个方法都有一个独立的SqlSession,这意 ...

  3. Codeforces 1169A Circle Metro

    题目链接:codeforces.com/contest/1169/problem/A 题意:有俩个地铁,一个从 1 → 2 → …→ n → 1→ 2 →…, 一个 从 n → n-1 →…→ 1 → ...

  4. Gerrit(1): Manage Projects

    1) Register an openid account https://login.ubuntu.com/+login 2) Custom settings set SSH pubkey set ...

  5. opencv——常见的操作

    一 图像阈值处理 准备一张灰度图像 阈值处理通常是设定一个阈值,让图片的所有像素点的值与其比较做出一系列的操作. 在opencv常用的阈值处理函数有五种,分别是THRESH_BINARY.THRESH ...

  6. python--常用模块:collections 、time、random

      一.collections 模块 1:nametuple 生成可以用名字访问内容的元祖 from collections import namedtuple point=namedtuple('p ...

  7. 关于第一次将STM32与电脑连接情况

    安装了Keil(ARM)版本之后,不管是自己编程,还是配套的程序运行.我们都想把它下载到STM32芯片里面,在板子上运行.这里介绍几种方法. 1.用J-LINK下载调试. 这个工具,可以直接点击kei ...

  8. JS window对象 History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能。语法: window.history.[属性|方法]

    History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能. 注意:从窗口被打开的那一刻开始记录,每个浏览器窗口.每个标签页乃至每个框架,都 ...

  9. Visio2016专业版永久激活码

    Visio2016专业版永久激活码: [Key]:NKVJM-8MTT4-8YDFR-6738M-DPFJH [Key]:W9WC2-JN9W2-H4CBV-24QR7-M4HB8 [Key]:7K8 ...

  10. Delphi StringGrid常用属性和常用操作

    StringGrid组件用于建立显示字符串的网格,与电子表格相似.它可使表格中的字符串和相关对象操作简单化.StringGrid组件提供了许多可控制网格外观念的属性,以及利用表格的结构响应用户操作的事 ...