IOS 開發之 Method Swizzling + Category

 

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.

相關文章
相關標籤/搜索