Objective-C 的运行时中最具争议的黑魔法:method swizzling

Objective-C 的运行时中最具争议的黑魔法:method swizzling_第1张图片

Selector(typedef struct objc_selector *SEL):

在运行时 Selectors 用来代表一个方法的名字。Selector 是一个在运行时被注册(或映射)的C类型字符串。Selector由编译器产生并且在当类被加载进内存时由运行时自动进行名字和实现的映射。

Method(typedef struct objc_method *Method):

方法是一个不透明的用来代表一个方法的定义的类型。

Implementation(typedef id (*IMP)(id, SEL,...)):

这个数据类型指向一个方法的实现的最开始的地方。该方法为当前CPU架构使用标准的C方法调用来实现。该方法的第一个参数指向调用方法的自身(即内存中类的实例对象,若是调用类方法,该指针则是指向元类对象metaclass)。第二个参数是这个方法的名字selector,该方法的真正参数紧随其后。

+ (void)load {//swizzling应该只在+load中完成

staticdispatch_once_tonceToken;//** swizzling 应该只在 dispatch_once 中完成**

dispatch_once(&onceToken, ^{

SELoriginalSelector =@selector(viewWillAppear:);

SELswizzledSelector =@selector(xlsn0w_viewWillAppear:);

MethodoriginalMethod =class_getInstanceMethod([selfclass], originalSelector);

MethodswizzledMethod =class_getInstanceMethod([selfclass], swizzledSelector);//获取实例方法

BOOLisAddMethod =class_addMethod([selfclass], originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));

if(isAddMethod) {

class_replaceMethod([selfclass], swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));

}else{

method_exchangeImplementations(originalMethod, swizzledMethod);

}

#pragma mark - Method Swizzling

- (void)xlsn0w_viewWillAppear:(BOOL)animated {

[selfxlsn0w_viewWillAppear:animated];

NSLog(@"viewWillAppear: %@",self);

}

//swizzling应该只在+load中完成。

//在Objective-C的运行时中,每个类有两个方法都会自动调用。

//+load是在一个类被初始装载时调用,

//+initialize是在应用第一次调用该类的类方法或实例方法前调用的。两个方法都是可选的,并且只有在方法被实现的情况下才会被调用。

+ (void)initialize {

}

@end

你可能感兴趣的:(Objective-C 的运行时中最具争议的黑魔法:method swizzling)