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 ...
随机推荐
- gitlab 日常运维命令
2018-10-24 gitlab查看版本 cat /opt/gitlab/embedded/service/gitlab-rails/VERSION 查看gitlab服务状态命令 gitlab-ct ...
- 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类
不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...
- HAProxy advanced Redis health check---ref
http://blog.exceliance.fr/2014/01/02/haproxy-advanced-redis-health-check/ HAProxy advanced Redis hea ...
- Python编码规范杂记(很乱:))
Python编码规范 导入模块 每一个(第三方)模块的导入都需要两个import语句, 如下 使用import some的方式导入模块, 如果有还有子模块的话, 则from father.son im ...
- 从零开始写C# MVC框架之--- 配置log4日志
在框架中配置日志分2步,一个是在帮助项目Zy.Utilities--Zy.Utility.Core中新建log类,封装写入日志方法,还需要在Zy.Utility.Core添加 log4net 的引用 ...
- jquery 获取easyui combobox选中的值、赋值
jquery easyui combobox 控件支持单选和多选 1.获取选中的值 $('#comboboxlist').combobox('getValue'); //单选时 $('#combob ...
- 认识Spring AOP
Spring AOP AOP是Aspect/'æspekt/ Oriented/ɔːrɪentɪd/ Programming的缩写,意为:面向切面编程. 是什么 通过预编译方式和运行期动态代理实现程序 ...
- CSP学习之导出密钥BLOB 解析
通过CryptExportKey( hKey, NULL, PUBLICKEYBLOB,0, NULL, &dwBlobLen) 函数导出的公钥信息如下: 06 02 00 00 00 A4 ...
- iOS开发之GCD基础
重新回顾.学习GCD.Block.先贴出一篇不错的讲解GCD基础使用的文章 原文地址:http://blog.csdn.net/aolan1108/article/details/17283415 做 ...
- -ms-zoom property
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...