ios runtime 汇总
来源:互联网 发布:linux mmap 实例 编辑:程序博客网 时间:2024/06/05 19:48
本篇文章将一些runtime函数进行一下汇总说明:
- 一iOS消息机制
- 二函数交换 method_exchangeImplementations
- 三添加函数 class_addMethod
- 四获取属性及成员变量
- 五归档
一、iOS消息机制
//iOS内部都是通过消息机制实现各个功能的//最好的体现就是通过指令`clang -rewrite-objc`实现objc到c++的转换,然后就可以看到里面的代码:int main(int argc, char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init")); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")))); }}//runtime - c++- (void)runtime_clangCode { Person *p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc")); p = objc_msgSend(p, sel_registerName("init")); objc_msgSend(p, @selector(eat));}//上面代码等同于 Person *p = [[Person alloc]init];`
二、函数交换 < method_exchangeImplementations >
Method Swizzing是发生在运行时的,主要用于在运行时将两个Method进行交换,我们可以将Method Swizzling代码写到任何地方,但是只有在这段Method Swilzzling代码执行完毕之后互换才起作用。
我们应该在那个地方实现函数的IMP交换呢?
没错,load函数,它是先于
main
函数执行的,因此在这里执行可以确保函数在调用之前,函数的实现部分已经完成交换;如下:
+ (void)load {
Method methodOld = class_getClassMethod([self class], @selector(URLWithString:));
Method methodNew = class_getClassMethod([self class], @selector(hook_URLWithString:));
method_exchangeImplementations(methodOld, methodNew);
}
对于NSArray、NSMutableArray、NSDictionary、NSMutableDictionary又不一样,具体见图:
三、添加函数 < class_addMethod >
当我们调用一个不存在的函数式就会报异常,这时我们可以通过添加一个错误处理函数来进行处理:
//解决类方法+ (BOOL)resolveClassMethod:(SEL)sel { class_addMethod([self class], sel, (IMP)haha, "V:@"); return [super resolveClassMethod:sel];}//解决实例方法+ (BOOL)resolveInstanceMethod:(SEL)sel { class_addMethod([self class], sel, (IMP)haha, "V:@"); return [super resolveInstanceMethod:sel];}void haha () { NSLog(@"访问了一个不存在的函数!");}
四、获取属性及成员变量
//获取成员变量 unsigned int count; Ivar *ivars = class_copyIvarList([self class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char *keyChar = ivar_getName(ivar); const char *type = ivar_getTypeEncoding(ivar); NSLog(@"type :%s",type); NSString *key = [NSString stringWithCString:keyChar encoding:NSUTF8StringEncoding]; id value = [self valueForKey:key];//获取属性 unsigned int count; objc_property_t *props = class_copyPropertyList([self class], &count); for (int i = 0; i < count; i++) { objc_property_t prop = props[i]; const char *proChar = property_getName(prop); NSString *key = [NSString stringWithCString:proChar encoding:NSUTF8StringEncoding]; id value = [self valueForKey:key]; }
五、归档
普通数据可以进行归档处理,如果一个对象需要实现NSCoding协议才可以进行归档操作;
下面说一个简单的归档(假设我们有一个Person类)
//1、实现NSCoding协议#import "Person.h"#import <objc/message.h>@interface Person()<NSCoding>@end@implementation Person- (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { unsigned int count; Ivar *ivars = class_copyIvarList([self class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char *keyChar = ivar_getName(ivar); const char *type = ivar_getTypeEncoding(ivar); NSLog(@"type :%s",type); NSString *key = [NSString stringWithCString:keyChar encoding:NSUTF8StringEncoding]; id value = [aDecoder decodeObjectForKey:key]; [self setValue:value forKey:key]; } free(ivars); } return self;}- (void)encodeWithCoder:(NSCoder *)aCoder { unsigned int count; Ivar *ivars = class_copyIvarList([self class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char *keyChar = ivar_getName(ivar); const char *type = ivar_getTypeEncoding(ivar); NSLog(@"type :%s",type); NSString *key = [NSString stringWithCString:keyChar encoding:NSUTF8StringEncoding]; id value = [self valueForKey:key]; [aCoder encodeObject:value forKey:key]; } free(ivars);}@end//2、设置一个归档路径//获取归档路径- (NSString *)path { NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; path = [path stringByAppendingPathComponent:@"p.arc"]; return path;}//3、归档实现//遍历属性、归档- (void)runtime_archive { Person *p = [[Person alloc]init]; p.name = @"li"; p.age = 18; [NSKeyedArchiver archiveRootObject:_p toFile:[self path]];}//4、解归档- (void)runtime_unArchive { Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:[self path]]; NSLog(@"person--:%@",p);}
阅读全文
0 0
- ios runtime 汇总
- [runtime] iOS-Runtime-Headers
- iOS runtime
- iOS Runtime
- iOS-runtime
- iOS Runtime
- IOS Runtime
- IOS - RunTime
- ios runtime
- ios runtime
- ios runtime
- iOS Runtime
- iOS runtime
- ios runtime
- iOS Runtime
- iOS - Runtime
- iOS--Runtime
- iOS runtime
- adb shell 命令查看屏幕尺寸
- libpcap原理及使用
- 融云 解决用户头像会话列表不显示问题
- 自定义View的学习2
- 第十五章:泛型(伪泛型)
- ios runtime 汇总
- Java最常用的英语单词
- c++ 对象坐标相加重载
- 【Scikit-Learn 中文文档】大规模计算的策略: 更大量的数据
- 将c风格的注释转换成cpp风格
- 指针练习-17
- VS进行性能分析
- CORS 跨域 实现思路及相关解决方案
- 值得奋斗的