ios 分类中若是增长的方法与被扩展的类方法名重复,则原方法就无法被调用….看如下例子ios
例如:函数
@interface ClassA : NSObject.net
- (NSString *) myMethod;blog
@endget
@implementation ClassAio
- (NSString*) myMethod {return @”class A”; }class
@endimport
//Category扩展
@interface ClassA (CategoryB)select
- (NSString *) myMethod;
@end
@implementation ClassA(CategoryB)
- (NSString*) myMethod {return @” class B”; }
@end
当 调用 [ClassA myMethod] 时候 会返回 class B .. 由于原类中的方法被扩展彻底重写,若是用户想要执行原类中的myMethod方法, cocoa中用相似类交换的方法解决这一问题 称为MethodSwizzling。Swizzling一词是“搅动、混合”之意,经常使用于鸡尾酒制做。因此Method Swizzling实际上是方法混合或方法交换。假设有一个类Test,它有一个方法length:
-(NSUInteger)length{
return 4571;
}
咱们想为Test定义一个类别,并覆盖这个方法,但同时,咱们还想调用Test类的默认实现。所以咱们能够这样写:
#import<objc/runtime.h>
@implementation Test(Logging)
- (NSUInteger)logLength {
NSUInteger length = [self logLength];
NSLog(@”Test Logging: %d”, length);
return length;
}
+ (void)load {
method_exchangeImplementations(class_getInstanceMethod(self,@selector(length)), class_getInstanceMethod(self, @selector(logLength)));}
@end
提示: swizzling没法在类簇上使用。
首先看load方法。在load方法中咱们调用了鸡尾酒魔法“method_exchangeImpementations”函数。这个函数将实例方法(在这里,实际上是类别方法)length和logLength方法的实现进行交换。也就是说,当咱们调用length时,其实是调用logLength,当咱们调用logLength时,其实是调用length。
实际上,一个方法的方法名和方法体是分开的。方法体是花括号 {} 之间的代码,即方法的 IMP,而在这以前的是方法名,即 SEL。一般状况下,SEL 是与 IMP 匹配的,但在 swizzling以后,length方法的SEL仍是叫作length,但IMP却变成了logLength的IMP,logLength的IMP却变成了length的IMP.