一、method-swizzling
+ (void)methodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL
{
if (!cls)
NSLog(@"传入的交换类不能为空");
Method oriMethod = class_getInstanceMethod(cls,oriSEL);
Method swiMethod = class_getInstanceMethod(cls,swizzledSEL);
method_exchangeImplementations(oriMethod,swiMethod);
/*
原本:
oriSEL -> oriIMP
swiSEL -> swiIMP
交换后:
oriSEL -> swiIMP
swiSEL -> oriIMP
*/
}
1、操作时机
放在load方法中操作,原因 :
- 调用时机早,在main函数前调用
- 系统自动调用
- 唯一性:load方法不会被覆盖,因此保证了安全性
注:若手动调用load方法还是会执行一次交换,方法就会交换城原状,所以最好用dispatch_once
2、坑
-
父类中 有方法A,子类没有实现方法A,但实现了方法B
此时在子类的分类的load方法中对方法A与方法B进行交换
现象:
- 子类生成的对象调用方法A正常执行,没有任何问题
- 父类生成的对象调用方法A后crash,报错为“方法B未实现”,因为父类拿不到子类方法B的实现
注:不要在子类里瞎搞父类的方法
子类做方法交换时,不应该影响到父类,不应该让父类去调用子类的方法
+ (void)betterMethodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL { if (!cls) NSLog(@"传入的交换类不能为空"); Method oriMethod = class_getInstanceMethod(cls,oriSEL); Method swiMethod = class_getInstanceMethod(cls,swizzledSEL); // 该处添加了一个名为方法A但指针指向方法B的方法,即SEL_A`->IMP_B // A`代表子类中再次实现的A BOOL didAddMethod = class_addMethod(cls,oriSEL,method_getImplementation(swiMethod),method_getTypeEncoding(swiMethod)); if (didAddMethod) { // 之前报错是因为子类拿自己的方法B去交换了父类的方法A,父类在调用方法B的时候找不到方法B,子类做方法交换时,不应该影响到父类,不应该让父类去调用子类的方法 // 所以这里子类自己实现了方法A即A`,并且将方法B的SEL指向->父类方法A的IMP class_replaceMethod(cls,swizzledSEL,method_getImplementation(oriMethod),method_getTypeEncoding(oriMethod)); // 所以当子类对象调用方法A的时候会走方法B,因为调的实际上是A` // 当父类对象调用方法A时,就是调用的原本父类实现的方法A,原本的方法A在这里没有发生交换 } else { method_exchangeImplementations(oriMedthod,swiMedthod); } } -
父类也没有实现A,子类也没有实现A,父类和子类的方法A的IMP都没有
此时,用子类对象调用方法A
现象:发生了递归
原因: 因为没有IMP_A,所以方法交换会失败,导致的结果是
SEL_A -> IMP_B,SEL_B -> IMP_B+ (void)bestMethodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL { if (!cls) NSLog(@"传入的交换类不能为空"); Method oriMethod = class_getInstanceMethod(cls, oriSEL); Method swiMethod = class_getInstanceMethod(cls, swizzledSEL); if (!oriMethod) { class_addMethod(cls, oriSEL, method_getImplementation(swiMethod), method_getTypeEncoding(swiMethod)); method_setImplementation(swiMethod, imp_implementationWithBlock(^(id self, SEL _cmd){ }));// 给一个空代码块相当于IMP_A } BOOL didAddMethod = class_addMethod(cls, oriSEL, method_getImplementation(swiMethod), method_getTypeEncoding(swiMethod)); if (didAddMethod) { class_replaceMethod(cls, swizzledSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)); }else{ method_exchangeImplementations(oriMethod, swiMethod); } } -
类方法会如何?
二、isKindOfClass和isMemberOfClass
+ (BOOL)isKindOfClass:(Class)cls {
// object_getClass((id)self) 是元类
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
// 当传进来的类cls == self的元类或自己元类的父类的时候返回yes
// 所以当cls = NSObject && self = NSObject 时返回YES
// 当cls = NSObject && self = 其他类时,也返回YES
// 目前个人判断:
// cls只要不是NSObject都会返回NO,只要是NSObject,就会返回YES
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;// 永远返回NO
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
三、[self class] 和 [super class]
- (Class)class {
return object_getClass(self);
}
- (Class)superclass { // 并不会走这个方法,因为不是[self superclass]
return [self class]->superclass;
}
[super class] 相当于 objc_msgSendSuper(&objc_super, class)
// [self class] 是self发送的class消息
// [super class] 是&objc_super发送的class消息,但是传入class的self是objc_super给的self
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver; // 就是self
__unsafe_unretained _Nonnull Class super_class; // 父类
/* super_class is the first class to search */
};