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 ...
随机推荐
- python3 模块安装列表
pip install scrapy pip install twisted pip install BeautifulSoup4 pip install lxml pip install Pillo ...
- C#中if和#if区别
if的作用是程序流控制,会直接编译.执行.#if是对编译器的指令,其作用是告诉编译器,有些语句行希望在条件满足时才编译. --------------------------------------- ...
- 实现类似tail -f file功能
python版本py3 tail -f file是打印最后10行,然后跟踪文件追加的内容打印出来. python3 以为本方式打开的话,不能回退(f.seek(-1,1)),所有以'rb'方式打开文件 ...
- mac下安装ionic
我的mac系统是EI Capitan,如下图所示. ionic是一个跨平台的框架,能够提供高效hybrid app的开发,而且性能接近于原生态,具体请参考:http://ionicframework. ...
- Linux定时任务与开机自启动脚本(cron与crontab)
开机自启动脚本 网上常见的脚本开机自启方法是: 假设要自启的脚本位于 /home/user/test.sh 给脚本可执行的权限 sudo chmod +x /home/user/test.sh 将脚本 ...
- elasticSearch请求流程图
- 数据从mysql迁移到hbase的一些思考及设计
一.进行迁移的原因 由于业务的发展,使用mysql进行建立索引进行搜索已经造成数据流的瓶颈卡在了数据库io,例如每次dump全表的时候,会造成压力过大,造成耗时很长,并且当前的数据量基本上已经达到了亿 ...
- FFmpegInterop 库在 Windows 10 应用中的编译使用
FFmpegInterop 简介 FFmpegInterop 是微软推出的封装 FFmpeg 的一个开源库,旨在方便在 Windows 10.Windows 8.1 以及 Windows Phone ...
- oracle UDT 有关数据字典的研究
1.数据及类型准备 创建了一个自定义类型 create or replace type addr_type as object( street varchar2(30); city varchar2( ...
- servlet中this.getServletContext(); this.getServletConfig().getServletContext(); 的区别
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用.ServletConfig对象中维护了ServletContext对象的引用,开发人 ...