iOS开发——高级技术OC篇&运行时(Runtime)机制
运行时(Runtime)机制
官方介绍:
这里我们主要关注的是最后一种!
下面来看看Runtime的相关总结
#pragma mark 获取属性成员
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 unsigned int count = 0; 2 3 Ivar *ivars = class_copyIvarList([iCocosObject class], &count); 4 5 // Ivar *ivars = class_copyMethodList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>) 6 7 // Ivar *ivars = class_copyPropertyList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>); 8 9 // Ivar *ivars = class_copyProtocolList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>) 10 11 12 13 for (int i = 0; i < count; i++) { 14 15 Ivar ivar = ivars[i]; 16 17 18 19 NSString *name = @(ivar_getName(ivar)); 20 21 NSLog(@"%@", name); 22 23 24 25 NSLog(@"*****************"); 26 27 const char *iv = ivar_getName(ivar); 28 29 30 31 32 33 NSLog(@"%s", iv); 34 35 36 37 NSLog(@"*****************"); 38 39 const char *ivs = ivar_getTypeEncoding(ivar); 40 41 42 43 NSLog(@"%s", ivs); 44 45 }
#pragma mark 获取方法
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 unsigned int meth = 0; 2 3 Method *met = class_copyMethodList([iCocosObject class], &meth); 4 5 for (int i = 0; i < meth; i++) { 6 7 Method m = met[i]; 8 9 10 11 SEL sel = method_getName(m); 12 13 NSString *str = NSStringFromSelector(sel); 14 15 16 17 NSLog(@"%@",str); 18 19 } 20 21
#pragma mark 获取协议
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 unsigned int pro = 0; 2 3 Protocol * __unsafe_unretained *proto = class_copyProtocolList([iCocosObject class], &pro); 4 5 for (int i = 0; i < pro; i++) { 6 7 Method p = (__bridge Method)(proto[i]); 8 9 10 11 const char *pr = protocol_getName((__bridge Protocol *)(p)); 12 13 // NSString *str = NSStringFromSelector(pr); 14 15 16 17 NSLog(@"%s",pr); 18 19 } 20 21
#pragma mark 获取属性
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 unsigned int xs = 0; 2 3 objc_property_t *xsL = class_copyPropertyList([iCocosObject class], &xs); 4 5 for (int i = 0; i < xs; i++) { 6 7 objc_property_t xslist = xsL[i]; 8 9 10 11 const char *x = property_getName(xslist); 12 13 // NSString *str = NSStringFromSelector(x); 14 15 16 17 NSLog(@"%s",x); 18 19 } 20 21 22 23 24 25 // objc_msgSend() 26 27 // objc_getClass(<#const char *name#>); 28 29 // sel_registerName(<#const char *str#>); 30 31 32 33 // iCocosView *view = objc_msgSend(objc_msgSend(objc_getClass("iCocosView"), sel_registerName("alloc")), sel_registerName("init")); 34 35 36 37
#pragma mark 实现方法混淆
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 Method one = class_getClassMethod([iCocosObject class], @selector(iCocosMethos)); 2 3 Method two = class_getClassMethod([iCocosObject class], @selector(iCocosMetho)); 4 5 method_exchangeImplementations(one, two); 6 7 8 9 Method o = class_getInstanceMethod([iCocosObject class], @selector(iCocosMethos)); 10 11 Method t = class_getInstanceMethod([iCocosObject class], @selector(iCocosMetho)); 12 13 method_exchangeImplementations(o, t); 14 15 16 17 // class_getInstanceSize(<#__unsafe_unretained Class cls#>); 18 19 // class_getInstanceVariable(<#__unsafe_unretained Class cls#>, <#const char *name#>); 20 21 // class_getMethodImplementation_stret(<#__unsafe_unretained Class cls#>, <#SEL name#>); 22 23 24 25 // class_getClassVariable(<#__unsafe_unretained Class cls#>, <#const char *name#>); 26 27 // class_getSuperclass(<#__unsafe_unretained Class cls#>); 28 29 30 31 // class_getProperty(<#__unsafe_unretained Class cls#>, <#const char *name#>); 32 33 // class_getName(<#__unsafe_unretained Class cls#>); 34 35 36 37 38 39 40 41 // class_replaceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>); 42 43
#pragma mark 增加
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 // class_addIvar(<#__unsafe_unretained Class cls#>, <#const char *name#>, <#size_t size#>, <#uint8_t alignment#>, <#const char *types#>); 2 3 // class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>); 4 5 // class_addProperty(<#__unsafe_unretained Class cls#>, <#const char *name#>, <#const objc_property_attribute_t *attributes#>, <#unsigned int attributeCount#>); 6 7 // class_addProtocol(<#__unsafe_unretained Class cls#>, <#Protocol *protocol#>); 8 9
#pragma mark 替换系统的addObject:(给数组或者其他类型做分类)
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
1 //在load中实现下面的代码 2 3 Method ic = class_getInstanceMethod(NSClassFromString(@"_NSArrayM"), @selector(iCocosobject:)); 4 5 Method add = class_getInstanceMethod(NSClassFromString(@"_NSArrayM"), @selector(addObject:)); 6 7 method_exchangeImplementations(ic, add); 8 9 10 11 12 13 //实现iCocosobject方法:(实现相应的功能,这里只是去掉非空) 14 15 // if (object != nil) { 16 17 // [self iCocosobject:object]; 18 19 // } 20 21
#pragma mark 消息机制
/******************************************************************************
* *
* Inquiry macros *
* *
* iCocos--Description *
* *
******************************************************************************/
objc_msgSend(); // objc_getClass(<#const char *name#>); // objc_getMetaClass(<#const char *name#>); // objc_getClassList(<#__unsafe_unretained Class *buffer#>, <#int bufferCount#>); // objc_getProtocol(<#const char *name#>); // object_getIvar(<#id obj#>, <#Ivar ivar#>); // objc_getRequiredClass(<#const char *name#>); // objc_getAssociatedObject(<#id object#>, <#const void *key#>);//关联对象 } @end
来看看我们平时使用OC编写的代码转成C++之后是什么样的
创建一个分类实现任何对象都可以使用方法混淆
1 2 3 @implementation NSObject(Extension) 4 5 6 7 /** 8 9 * 给NSObject添加一个分类 10 11 */ 12 13 14 15 +(void)swizzleClassMethod:(Class)class originalSelector:(SEL)originSelector otherSelector:(SEL)otherSelector 16 17 { 18 19 Method other = class_getClassMethod(class, otherSelector); 20 21 Method origin = class_getClassMethod(class, originSelector); 22 23 method_exchangeImplementations(other, origin); 24 25 } 26 27 28 29 +(void)swizzleInstanceMethod:(Class)class originalSelector:(SEL)originSelector otherSelector:(SEL)otherSelector 30 31 { 32 33 Method other = class_getInstanceMethod(class, otherSelector); 34 35 Method origin = class_getInstanceMethod(class, originSelector); 36 37 method_exchangeImplementations(other, origin); 38 39 } 40 41 @end
应用实例--------------------------------------------------
一:关联对象:给某一个类在运行的时候动态的增加一个成员变量
1 @interface NSObject(iCocos) 2 3 4 5 //头文件中声明一个属性 6 7 @property (nonatomic, assign) double height; 8 9 10 11 @end 12 13 14 15 16 17 @implementation NSObject(iCocos) 18 19 20 21 static double heightKey;//用来参考 22 23 24 25 -(void)setHeight:(double)height 26 27 { 28 29 objc_setAssociatedObject(self, &heightKey, @(height), OBJC_ASSOCIATION_ASSIGN); 30 31 } 32 33 34 35 -(double)height 36 37 { 38 39 return [objc_getAssociatedObject(self, &heightKey) doubleValue]; 40 41 } 42 43 44 45 @end 46 47
二:归档
三:字典转模型:
之前使用的方法;
使用运行时
注意必须保证字典中的属性名和模型中的属性名一模一样
完善代码:
1 @implementation NSObject (Model) 2 3 4 5 + (instancetype)objcWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict 6 7 { 8 9 10 11 12 13 id objc = [[self alloc] init]; 14 15 16 17 unsigned int count = 0; 18 19 Ivar *ivars = class_copyIvarList(self, &count); 20 21 22 23 for (int i = 0; i < count; i++) { 24 25 Ivar ivar = ivars[i]; 26 27 28 29 NSString *name = @(ivar_getName(ivar)); 30 31 32 33 name = [name substringFromIndex:1]; 34 35 36 37 id value = dict[name]; 38 39 40 41 if (value == nil) { 42 43 44 45 if (mapDict) { 46 47 NSString *mapName = mapDict[name]; 48 49 50 51 value = dict[mapName]; 52 53 } 54 55 56 57 } 58 59 60 61 [objc setValue:value forKeyPath:name]; 62 63 } 64 65 66 67 68 69 return objc; 70 71 } 72 73 74 75 @end
四:封装框架:MJExtension
iOS开发——高级技术OC篇&运行时(Runtime)机制的更多相关文章
- iOS开发——高级UI—OC篇&退出键盘
退出键盘 iOS开发中键盘的退出方法用很多中我们应该在合适的地方使用合适的方法才能更好的提高开发的效率和应用的性能 下面给大家介绍几种最常用的键盘退出方法,基本上iOS开发中的键盘退出方法都是这几种中 ...
- iOS开发——使用技术OC篇&简单九宫格锁屏功能的实现与封装
简单九宫格锁屏功能的实现与封装 首先来看看最后的实现界面. 在这开始看下面的内容之前希望你能先大概思考活着回顾一下如果 你会怎么做,只要知道大概的思路就可以. 由于iphone5指纹解锁的实现是的这个 ...
- iOS开发——高级技术精选OC篇&Runtime之字典转模型实战
Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...
- iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势
使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...
- iOS开发——底层OC篇&运行时常用
运行时常用 什么是Runtime(前面的文章已经说的很清楚了,这里就简单的介绍一下) 我们写的代码在程序运行过程中都会被转化成runtime的C代码执行,例如[target doSomething]; ...
- ios开发——实用技术篇OC篇&iOS的主要框架
iOS的主要框架 阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用青花瓷抓取网络数据
网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据
网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...
- iOS开发——新特性OC篇&IOS9 SDK新特性
iOS9 SDK新特性 WWDC 2015苹果开发者大会是移动开发者一年一度的盛会,InfoQ中文站除了第一时间整理Keynote内容分享给大家之外,还邀请了资深的一线开发者分享他们的收获.本文为王巍 ...
随机推荐
- React Ntive 学习手记
React使今年来比较热门的前端库,之所以说是库呢,因为React.js是应用于MVC中的V层, 它并不是一个完整的MVC框架,所以,我也不知称之为框架了. 不过这并不影响React的火热. 混合应用 ...
- Windows下Spark单机环境配置
1. 环境配置 a) java环境配置: JDK版本为1.7,64位: 环境变量配置如下: JAVA_HOME为JDK安装路径,例如D:\software\workSoftware\JAVA 在pa ...
- [转]Redis之七种武器
长生剑.孔雀翎.碧玉刀.多情环.离别钩.霸王枪.拳头是古龙笔下的七种武器,而本文打算将Redis的几种使用方式 Strings.Hashs.Lists.Sets.Sorted Sets.Pub/Sub ...
- 联想Phab2 Pro Tango手机测评
评分:8分 优点:创新的AR应用手机,可以当成一个游戏机了 缺点:还没找到 评语:打开新世界的大门,现实与虚拟结合,枯燥的生活添加一点幻想,走进童话般的梦幻王国,丰富多彩 包装 外形 打开主界面 最主 ...
- bdb log file 预设长度的性能优化
看代码随手记:log_put.c, __log_write() /* * If we're writing the first block in a log file on a filesystem ...
- [Leetcode][JAVA] Minimum Depth of Binary Tree && Balanced Binary Tree && Maximum Depth of Binary Tree
Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the n ...
- Web Workers
在 Web Workers 中使用 postMessage 和 onmessage 首先,需要在客户端页面的 JavaScript 代码中 new 一个 Worker 实例出来,参数是需要在另一个线程 ...
- [Xpand] Error 1 Invalid option '6' for /langversion; must be ISO-1, ISO-2, 3, 4, 5 or Default
原因是用的vs2015 默认用了c#6 ,但是在没安装.net 4.6 环境下编译失败. 解决办法很简单,修改 6 为 5 做降级就可以了. 1.nuget install DotNetCompile ...
- PHP多文件上传(二维数组$_FILES('文件域的名称'),move_uploaded_file(‘临时文件名’,‘新的文件名’))
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 拾遗——java多线程
由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁.所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这 ...