runtime 是系统底层的c语言api集合

98 阅读2分钟
/// oc类的struct -----------------------
1.id 的c代码,oc的class都是struct,包括block最终也是struct. id 可以表示任何对象,因为对象类型只有运行期才能确认。
struct objc_object {
    Class isa;// 对象首个属性是isa指针
} *id;

2. Class 
typedef struct objc_class *Class;
struct objc_class { 
    Class isa                                 OBJC_ISA_AVAILABILITY; //说明是oc类。isa 指向的类的isa属性的类叫元类
#if !__OBJC2__
    Class super_class                         OBJC2_UNAVAILABLE; //本来的超类
    const char *name                          OBJC2_UNAVAILABLE;
    long version                              OBJC2_UNAVAILABLE; 
    long info                                 OBJC2_UNAVAILABLE; 
    long instance_size                        OBJC2_UNAVAILABLE; 
    struct objc_ivar_list *ivars              OBJC2_UNAVAILABLE; //成员变量列表
    struct objc_method_list **methodLists     OBJC2_UNAVAILABLE; //方法列表
    struct objc_cache *cache                  OBJC2_UNAVAILABLE; //方法缓存列表,会先在该列表寻找,若是没有找到会再次到methodLists寻找
    struct objc_protocol_list *protocols      OBJC2_UNAVAILABLE; //协议列表
#endif
}

3.SEL 是选择子的类型,选择子指的就是方法的名字。
  typedef struct objc_selector *SEL;

4.typedef struct objc_method *Method; 代表类中的某个方法的类型
struct objc_method {
    SEL method_name                    OBJC2_UNAVAILABLE;
    char *method_types                 OBJC2_UNAVAILABLE;
    IMP method_imp                     OBJC2_UNAVAILABLE;
}

5. Ivar代表类中实例变量的类型
  typedef struct objc_ivar *Ivar;
  struct objc_ivar {
    char *ivar_name                   OBJC2_UNAVAILABLE; 
    char *ivar_type                   OBJC2_UNAVAILABLE; 
    int ivar_offset                   OBJC2_UNAVAILABLE; 
#ifdef __LP64__
    int space                         OBJC2_UNAVAILABLE;
#endif
}

6. objc_property_t是属性
typedef struct objc_property *objc_property_t;
class_copyPropertyList(Class cls, unsigned int *outCount) 获取某个类的属性列表。
  
  
/// 消息转发-----------------------
id objc_msgSend (id self, SEL _cmd, ...); index=012...(接收者,选择子,参数)
  
对象在收到无法解读的消息后->resolveInstanceMethod->forwardingTargetForSelector->methodSignatureForSelector->forwardInvocation->doesNotRecognizeSelector

  // 1 对象在收到无法解读的消息后,可用于动态添加方法,方法决定是否动态添加方法。如果返回YES,则调用class_addMethod动态添加方法,消息得到处理,结束;如果返回NO,则进入下一步;
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    return NO;
}
// 2 处理未知的选择子,在这一步中,能不能把这条消息转给其他接收者来处理。会进入此方法,用于指定备选对象响应这个selector,不能指定为self。如果返回某个对象则会调用对象的方法,结束。如果返回nil,则进入下一步;
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return nil;
}

// 3 该方法签名,如果返回nil,则消息无法处理。如果返回methodSignature,则进入下一步。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if ([NSStringFromSelector(aSelector) isEqualToString:@"study"])
    {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}
// 4 调用该方法,我们可以通过anInvocation对象做很多处理,比如修改实现方法,修改响应对象等,如果方法调用成功,则结束。如果失败,则进入doesNotRecognizeSelector方法。
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation setSelector:@selector(play)];
    [anInvocation invokeWithTarget:self];
}

// 5 抛出异常,此异常表示选择子最终未能得到处理。
- (void)doesNotRecognizeSelector:(SEL)aSelector
{
    NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector));
}
  

/// 关联对象 (AssociatedObject)-----------------------
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
id objc_getAssociatedObject(id object, void *key)
void objc_removeAssociatedObjects(id object)
  
/// 方法替换,转换,设置新实现 -----------------------
class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
method_exchangeImplementations(Method m1, Method m2)
method_setImplementation(Method m, IMP imp)

参考文章:www.jianshu.com/p/3e050ec3b…