iOS开发系列-Runtime运用场景
概述
Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。
调用runtime
API需要导入都文件#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.文件存储.界面布局.离线推送.内 ...
随机推荐
- GF学习未解之谜
1.很奇怪事件管理器里面的用到的订阅事件里面的ID是通过typeof(xxx).GetHashCode()得到的,怎么解决id重复的问题? 2.log系统里面是不是直接全部当做多参数解决问题比较好?
- inode缓存与dentry缓存
1. inode缓存 1: struct inode { 2: /* RCU path lookup touches following: */ 3: umode_t i_mode; 4: uid_t ...
- java-day02
数据类型自动转换 要求:数据范围从小到大 数据类型强制类型转换 格式:范围小的数据类型 范围小的变量名 = (范围小的数据类型)原范围大的数据 注意事项: 1.可以会造成数据溢出或者是精度损失. 2. ...
- 这是<一起找打的约定>的改良版本
-- CREATE TABLE class ( -- cid INT(25)auto_increment PRIMARY KEY, -- caption VARCHAR(50) not NULL -- ...
- assignment of day four
目录 1.Numeric type (1)integer (2)float Usefulness Define How to use 2.string type Use Define How to u ...
- zabbix--监控的组件和进程介绍
上图是zabbix的架构,zabbix proxy(代理),可以减小IO并发. zabbix web GUI是用php写的画图工具,从数据库抓取数据. zabbix database zabbix获取 ...
- 如果手工启动chromedriver
使用selenium模拟登陆网站时,有些网站会识别chrome driver里的json信息,从而判断是不是爬虫程序,做到反爬效果.(比如知乎) 下面说明下怎么手动启动chromedriver 1). ...
- 使用Swagger2Markup归档swagger生成的API文档
文章出处: http://blog.didispace.com/swagger2markup-asciidoc/ 说明 项目中使用Swagger之后,我们能够很轻松的管理API文档,并非常简单的模拟接 ...
- 21-7-数组相关api
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 杭电多校第一场-M-Code
题目描述 After returning with honour from ICPC(International Cat Programming Contest) World Finals, Tom ...