iOS开发系列-Runtime运用场景
概述
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运用场景的更多相关文章
- iOS开发系列--Swift进阶
概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- IOS开发系列 --- 核心动画
原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列
因为最近面试了一些人,校招.初中级.高级.架构师,各种级别的,发现大家水平差异很大,有的高级的工程师很多问题都回答不上来,所以想梳理下iOS的知识点,写成一个系列,如果时间允许的话,会录制成视频放到网 ...
- iOS开发系列--让你的应用“动”起来【转载】
概览 原文链接:http://www.cnblogs.com/kenshincui/p/3972100.html 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列--通知与消息机制--转
来自:http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户 ...
- iOS开发系列之app的一天
本文主要讲述我对 iOS 开发的一些理解,希望能通过 app 从启动到退出,将一些的知识整合起来,形成一条知识链,目前涉及到的知识点有 runloop.runtime.文件存储.界面布局.离线推送.内 ...
随机推荐
- 2、Locust压力测试 实战
创建测试脚本 创建Test()类继承TaskSet类 创建beigong() 方法表示一个行为,访问北弓官网首页.用@task() 装饰该方法为一个任务.1表示一个Locust实例被挑选执行的权重,数 ...
- 通过Module读取寄存器的值
1: int eax; 2: _asm_("nop":"=a"(eax)); 3: printk("Get Eax Value:\n"); ...
- Bagging vs Boosting vs Stacking
原文地址:https://www.jianshu.com/p/9dacdc88d3ec Bagging 用于减小方差. 使用训练数据的不同随机子集(大小常等于训练数据,采用不放回的方式进行抽取)来训练 ...
- [已解决]报错JSONDecodeError
报错: 解决:
- 2019ICPC南京网络赛B super_log
题意:求a的a的a次方..一直求b次,也就是在纸上写个a,然后一直a次方a次方,对m取模,记为F(a,b,m)=pow(a,F(a,b-1,phi(m)) 解题思路:联系欧拉降幂,这个迭代的过程,我们 ...
- man bash
BASH(1) General Commands Manual BASH(1) NAME bash - GNU Bourne-Again SHell SYNOPSIS bash [options] [ ...
- Excel_VBA 常用代码
单元格编辑后改变背景色(6号,355832828) Dim oldvalue As Variant Private Sub Worksheet_Change(ByVal Target As Range ...
- 看了Google编码规范,我突然有个感觉
那么个编码规范,充分体现了西方人的自我感觉良好,以及以自己为中心的程度, 以及西方人对待事物的双重标准.
- python中 try、except、finally执行顺序
我们虽然经常用到try...except 作为异常补货,但是其实很少去研究try源码和机制,也许点进去看过,也是看不出个所以然来 class Exception(BaseException): &qu ...
- pandas读书笔记、重新索引
重新索引 pandas对象的一个重要方法是 reindex ,其作用是创建一个适应新索引的新对象. #reindex函数的参数 reindex(index,method,fill_value, ...