IOS Runtime的用法
什么是runtime?
1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型、C语言函数)
2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的
* 也就是说,平时我们编写的OC代码,最终都是转成了底层的runtime代码(C语言代码)
runtime有啥用?
1> 能动态产生一个类、一个成员变量、一个方法
2> 能动态修改一个类、一个成员变量、一个方法
3> 能动态删除一个类、一个成员变量、一个方法
常见的函数、头文件
#import <objc/runtime.h> : 成员变量、类、方法
Ivar * class_copyIvarList : 获得某个类内部的所有成员变量
Method * class_copyMethodList : 获得某个类内部的所有方法
Method class_getInstanceMethod : 获得某个实例方法(对象方法,减号-开头)
Method class_getClassMethod : 获得某个类方法(加号+开头)
method_exchangeImplementations : 交换2个方法的具体实现
#import <objc/message.h> : 消息机制
objc_msgSend(....)
#import "HMViewController.h"
#import "HMPerson.h"
#import <objc/runtime.h>
#import <objc/message.h> @interface HMViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView1;
@property (weak, nonatomic) IBOutlet UIImageView *iconView2; @property (nonatomic, strong) NSMutableArray *names;
@property (nonatomic, strong) NSArray *books; @end @implementation HMViewController - (NSMutableArray *)names
{
if (_names == nil) {
self.names = [NSMutableArray array];
}
return _names;
} - (void)viewDidLoad
{
[super viewDidLoad]; // NSDictionary *info = @{@"name" : @"jack", @"age" : @10};
//
// NSString *key = nil;
//
// NSLog(@"%@", info[key]); NSMutableDictionary *info = [NSMutableDictionary dictionary];
info[@"name"] = nil; // self.books = @[@"kiuhua", @"xxx"];
//
// NSLog(@"%@", self.books[4]); // [self addName:@"jack"];
// [self addName:@"rose"];
// [self addName:@"jim"];
//
// NSLog(@"%@", self.names[4]);
// NSLog(@"%@", [self.names objectAtIndex:4]);
} - (void)addName:(NSString *)name
{
[self.names addObject:name];
} - (void)imageSwizzle
{
// 什么是iOS Swizzle?利用运行时函数交换2个方法的实现 // BOOL iOS7 = [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;
// if (iOS7) {
// self.iconView1.image = [UIImage imageNamed:@"face_os7"];
// self.iconView2.image = [UIImage imageNamed:@"vip_os7"];
// } else {
// self.iconView1.image = [UIImage imageNamed:@"face"];
// self.iconView2.image = [UIImage imageNamed:@"vip"];
// }
self.iconView1.image = [UIImage imageNamed:@"face"];
self.iconView2.image = [UIImage imageNamed:@"vip"];
} - (void)testRuntimeIvar
{
// Ivar : 成员变量
unsigned int count = ;
// 获得所有的成员变量
Ivar *ivars = class_copyIvarList([HMPerson class], &count);
for (int i = ; i<count; i++) {
// 取得i位置的成员变量
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
const char *type = ivar_getTypeEncoding(ivar);
NSLog(@"%d %s %s", i, name, type);
} // HMPerson *p = [[HMPerson alloc] init];
// objc_msgSend(p, @selector(setAge:), 20); // NSLog(@"%d", p.age);
}
HMPerson.h /.m(获取所有成员变量)
#import <Foundation/Foundation.h> @interface HMPerson : NSObject <NSCoding>
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) double height;
- (void)run;
@end
#import "HMPerson.h"
#import <objc/runtime.h> @implementation HMPerson
- (void)run
{
NSLog(@"run----");
} - (void)encodeWithCoder:(NSCoder *)encoder
{
unsigned int count = ;
Ivar *ivars = class_copyIvarList([HMPerson class], &count);
for (int i = ; i<count; i++) {
// 取得i位置的成员变量
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
[encoder encodeObject:[self valueForKeyPath:key] forKey:key];
}
} @end
UIImage+Extension(交换2个方法的实现)
#import <objc/runtime.h> @implementation UIImage (Extension)
/**
* 只要分类被装载到内存中,就会调用1次
*/
+ (void)load
{
Method otherMehtod = class_getClassMethod(self, @selector(imageWithName:));
Method originMehtod = class_getClassMethod(self, @selector(imageNamed:));
// 交换2个方法的实现
method_exchangeImplementations(otherMehtod, originMehtod);
} + (UIImage *)imageWithName:(NSString *)name
{
BOOL iOS7 = [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;
UIImage *image = nil;
if (iOS7) {
NSString *newName = [name stringByAppendingString:@"_os7"];
image = [UIImage imageWithName:newName];
} if (image == nil) {
image = [UIImage imageWithName:name];
}
return image;
} @end
NSObject+Extension(交换2个方法的实现)
#import <objc/runtime.h> @implementation NSObject(Extension)
+ (void)swizzleClassMethod:(Class)class originSelector:(SEL)originSelector otherSelector:(SEL)otherSelector
{
Method otherMehtod = class_getClassMethod(class, otherSelector);
Method originMehtod = class_getClassMethod(class, originSelector);
// 交换2个方法的实现
method_exchangeImplementations(otherMehtod, originMehtod);
} + (void)swizzleInstanceMethod:(Class)class originSelector:(SEL)originSelector otherSelector:(SEL)otherSelector
{
Method otherMehtod = class_getInstanceMethod(class, otherSelector);
Method originMehtod = class_getInstanceMethod(class, originSelector);
// 交换2个方法的实现
method_exchangeImplementations(otherMehtod, originMehtod);
}
@end @implementation NSArray(Extension)
+ (void)load
{
[self swizzleInstanceMethod:NSClassFromString(@"__NSArrayI") originSelector:@selector(objectAtIndex:) otherSelector:@selector(hm_objectAtIndex:)];
} - (id)hm_objectAtIndex:(NSUInteger)index
{
if (index < self.count) {
return [self hm_objectAtIndex:index];
} else {
return nil;
}
} @end @implementation NSMutableArray(Extension)
+ (void)load
{
[self swizzleInstanceMethod:NSClassFromString(@"__NSArrayM") originSelector:@selector(addObject:) otherSelector:@selector(hm_addObject:)];
[self swizzleInstanceMethod:NSClassFromString(@"__NSArrayM") originSelector:@selector(objectAtIndex:) otherSelector:@selector(hm_objectAtIndex:)];
} - (void)hm_addObject:(id)object
{
if (object != nil) {
[self hm_addObject:object];
}
} - (id)hm_objectAtIndex:(NSUInteger)index
{
if (index < self.count) {
return [self hm_objectAtIndex:index];
} else {
return nil;
}
}
@end
IOS Runtime的用法的更多相关文章
- ios runtime swizzle
ios runtime swizzle @implementation NSObject(Extension) + (void)swizzleClassMethod:(Class)class orig ...
- ios runtime的相关知识
一.iOS runtime原理 对于runtime机制,在网上找到的资料大概就是怎么去用这些东西,以及查看runtime.h头文件中的实现,当然这确实是一种很好的学习方法,但是,其实我们还是不会知道r ...
- iOS Runtime 实践(1)
很多时候我们都在看iOS开发中的黑魔法——Runtime.懂很多,但如何实践却少有人提及.本文便是iOS Runtime的实践第一篇. WebView 我们这次的实践主题,是使用针对接口编程的方式,借 ...
- IOS NSUserDefaults 讲解 用法
IOS NSUserDefaults 讲解 用法 NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名.密码之类的,个人觉得使用NSUserDefaults ...
- 包建强的培训课程(11):iOS Runtime实战
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- iOS Runtime的消息转发机制
前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!! Runtime基本概念:https://www.cn ...
- iOS Runtime 实操练习
iOS Runtime 知识详解: http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/ 一般可以运行Runtime进行以下操作 ...
- iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制
你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...
- IOS runtime动态运行时二
在C#.Java中有编译时多态和运行时多态,在OC中,只有运行时的多态,这与它的运行机制有关.OC中,方法的调用是通过消息的传递来进行的.在IOS runtime动态运行时一http://www.cn ...
随机推荐
- PIE SDK打开栅格数据
1. 功能简介 GIS将地理空间数据表示为矢量数据和栅格数据.矢量数据模型使用点.线和多边形来表示具有清晰空间位置和边界的空间要素,如控制点.河流和宗地等,每个要素被赋予一个ID,以便与其属性相关联. ...
- 【Tensorflow】 Object_detection之liunx服务器安装部署步骤记录
环境:centos7+anaconda python3.6 步骤: 1.下载Models cd 到预存放目录下,执行: git clone https://github.com/tensorflow/ ...
- js动画实现&&回调地狱&&promise
1. js实现动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Java关键字final、static使用总结 (final static在容器中不可以改变容器但可以改变存放)
一.final 根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类.非抽象类成员方法和变量.你可能出于两种理解而需要阻止改变:设计或效 ...
- mysql 查询及 删除表中重复数据
CREATE TABLE `test` ( `id` INT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) NULL DEFAULT NULL, `a ...
- 【python数据分析】利用Anaconda在window上搭建数据分析环境
由于在进行数据分析过程中,需要安装一些第三方库,导致python总会报一些错误,现将通过利用Anaconda搭建数据分析环境,已测可用. 1.到官网上下载python:https://www.pyth ...
- C和C++中include 搜索路径的一般形式以及gcc搜索头文件的路径
C和C++中include 搜索路径的一般形式 对于include 搜索的路径: C中可以通过 #include <stdio.h> 和 #include "stidio.h&q ...
- SpringBoot - 工程搭建
SpringBoot 简介 1.Spring 的封装.其设计目的是用来简化 Spring 应用的初始搭建以及开发过程. 2.SpringCloud 微服务的基础 搭建环境 jdk 1.8 + mave ...
- WPF中嵌入Skyline提供的COM组件填坑
网上有很多关于在WPF中使用的Skyline提供的COM组件的教程,但大都雷同一律,其中很多的细节均为涉及,本文意在在其原基础上进行一些细节的补充. 工具:Visual Studio 2017 1. ...
- 开源TSDB简介--Druid
开源TSDB简介--Druid Druid是一个以Java编写的开源分布式列式数据存储. Druid的目标是快速提取大量事件数据,并提供低延迟的查询. 德鲁伊的名字来源于许多角色扮演游戏中的变形德鲁伊 ...