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 ...
随机推荐
- rsync 问题总结
Rsync服务常见问题汇总讲解:==================================1. rsync服务端开启的iptables防火墙 [客户端的错误] No route to ...
- linux 卡在进度条进不去解决办法之一
centos为例 一, 如下: 如果这个地方卡住了的话也许是你上次改了passwd文件,这个是其中一个情况. 如果刚刚开机就卡住了或者怎么卡住了的话在开机的读条时候摁esc显示读取的进程,根据显示的错 ...
- console命令详解:(转载学习)
Console命令详解,让调试js代码变得更简单 Firebug是网页开发的利器,能够极大地提升工作效率. 但是,它不太容易上手.我曾经翻译过一篇<Firebug入门指南>,介绍了一些 ...
- Java面试题03-访问权限控制
Java面试题03-访问权限控制 1. Java中的包主要是为了防止类文件命名冲突以及方便进行代码组织和管理,因此采用域名倒置的方式来进行命名: 2. Java解释器的运行过程:首先找到环境变量CLA ...
- 原生JS写的ajax函数
参照JQuery中的ajax功能,用原生JS写了一个ajax,功能相对JQuery要少很多,不过基本功能都有,包括JSONP. 调用的方式分为两种: 1. ajax(url, {}); 2. ajax ...
- 利用pandas生成csv文件
# -*- coding:UTF-8 -*- import json from collections import OrderedDict with open('dns_status.json',' ...
- indexOf.substr,substring,charAt的区别
var a = "asdfghjkl" alert(a.substr(1, 3)); // 从下标为1开始,往右数3个长度的数, 显示 sdf; alert(a.s ...
- MVC Request.UrlReferrer为null
使用情景,登录后返回登录前访问的页面. 这个时候用到了UrlReferrer var returnUrl = HttpContext.Current.Request.UrlReferrer != nu ...
- C#学习笔记4
1.C#只支持单一继承,若想要实现多重继承的效果.有2种方式: 第一种为传递继承,A为基类,B继承A,C继承B,通过传递来增迭要包含的元素,但这种继承的设计,在业务上具有明显的从属关系. 第二种为聚合 ...
- SQL注入和XSS攻击的原理
8.4 Web跨站脚本攻击 8.4.1 跨站脚本攻击的原理(1) 跨站脚本在英文中称为Cross-Site Scripting,缩写为CSS.但是,由于层叠样式表 (Cascading Style ...