1. 主类的方法和分类的方法重名,会如何调用?
如果重名的是+load方法,则先执行父类的load方法 ,其次主类的load方法,最后执行分类的load方法
如果重名的是+initialize,执行父类的initialize方法,然后分类的initialize方法会覆盖主类的initialize方法,导致主类的initialize方法不执行。 (initialize是在对象第一次发送消息的时候调用)
如果重名的是其他普通方法,则分类方法会覆盖主类方法
2.方法的本质?sel是什么?imp是什么?两者之间的关系又是什么?
3. Runtime是如何实现weak,为什么可以自动置为nil?
- 通过SideTable找到我们的weak_table
- weak_table根据referent找到或者创建weak_entry_t
- 然后append_referrer(entry,referrer)将我的新弱引用的对象加到entry
- 最后weak_entry_insert 把entry加入到我们的weak_table
4.Associate方法关联的属性,需要手动在delloc里面释放吗?
不需要 ,应为在dealloc的实现里面已经实现
dealloc ->_objc_rootDealloc(self)->obj->rootDealloc()->object_dispose()->objc_destructInstance()
5.Method Swizzling的坑与应用
- 首先Method Swizzling方法最好是能够放在+load或+initialize方法里面,保证第一次发送消息之前就已经执行了方法切换的代码
- method_exchangeImplementations()方法交换的本质: 交换imp(即方法的实现)
- 为避免Method Swizzling出现的各种坑,设计了一下实现代码:
@interface LGRuntimeTool : NSObject
/**
交换方法
@param cls 交换对象
@param oriSEL 原始方法编号
@param swizzledSEL 交换的方法编号
*/
+ (void)lg_bestMethodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL;
@end
@implementation LGRuntimeTool
+ (void)lg_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) {
// 在oriMethod为nil时,替换后将swizzledSEL复制一个不做任何事的空实现,代码如下:
class_addMethod(cls, oriSEL, method_getImplementation(swiMethod), method_getTypeEncoding(swiMethod));
method_setImplementation(swiMethod, imp_implementationWithBlock(^(id self, SEL _cmd){ }));
}
// 一般交换方法: 交换自己有的方法 -- 走下面 因为自己有意味添加方法失败
// 交换自己没有实现的方法:
// 首先第一步:会先尝试给自己添加要交换的方法 :personInstanceMethod (SEL) -> swiMethod(IMP)
// 然后再将父类的IMP给swizzle personInstanceMethod(imp) -> swizzledSEL
//oriSEL:personInstanceMethod
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);
}
}
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[LGRuntimeTool lg_bestMethodSwizzlingWithClass:self oriSEL:@selector(helloword) swizzledSEL:@selector(lg_studentInstanceMethod)];
});
}