使用总结
runtime开源代码
对象的关联:
- 设置关联值
void objc_setAssociatedObject(id object, const void *key, id value, objc _AssociationPolicy policy)
获取关联值
id objc_getAssociatedObject(id object, const void *key)
key和object保持一致
- 2 获取关联值
id objc_getAssociatedObject(id object, const void *key)
序列化,json->model转换
- 利用runtime进行coding操作,开发中常用的方案
/**归**/
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
free(ivars);
/** 解*/
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
id value = [self valueForKeyPath:key];
[aCoder encodeObject:value forKey:key];
}
free(ivars);
- model
/** 此处仅考虑单层模型*/
id objc = [[self alloc] init];
unsigned int count;
Ivar *ivarList = class_copyIvarList(self, &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSString *key = [keyName substringFromIndex:1];
id value = dict[key];
if (value) {
[objc setValue:value forKey:key];
}
}
- 方法交换代码来源
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(xxx_viewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
// ...
// Method originalMethod = class_getClassMethod(class, originalSelector);
// Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
方法调用
- 消息调用
objc_msgSend(receiver, selector)
工作原理:在所属类的方法列表中寻找对应的方法,成功匹配方法后会把结果缓存在“快递映射表”(hash)中,下次运行时候直接走映射表方法,快捷迅速。如果类方法中未匹配到对应方法会向上找父类的方法列表,最终找不到匹配的方法则进行消息转发机制
- 消息转发机制
+(BOOL) resolveInstanceMethod:(SEL)selector;
-(id)forwardingTargetForSelector:(SEL)selector
-(void)forwardInvocation:(NSInvocation*)invocation
在转发中处理