NSRuntime使用篇

使用总结
runtime开源代码

对象的关联:

    1. 设置关联值

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

在转发中处理

你可能感兴趣的:(NSRuntime使用篇)