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.