Swizzling:偷梁換柱的黑魔法

我們知道,OC是一門動態運行時語言。我們也知道,OC中的函數調用本質上其實是消息的發送:objc_MsgSend(someObject, @selector(methodName), parameters)所有要調用的函數,編譯階段是無法確定的,只有到運行的時候才能確定!正因為有此特性,所以在運行階段,我們都還可以做很多事,而要把本來應該實現的方法A,偷偷換成方法B,便是其中的一種,這種技術叫做:Method Swizzling(方法交換)!

具體相關的概念就不再啰嗦了,網上都有很多了,可以自行google或者查閱《Effective Objective-C 2.0 編寫高質量iOS與OS X 代碼的52個有效方法》的第13條,介紹的都比較詳細了。這里就總結一下相關的應用!

調試用

假如每次調用NSString的lowerCaseString方法時,不要每次都去NSLog,希望直接調用系統的方法時每次都可以輸出log,那么這時候就可以用到該技術:

@interface NSString (XPPMyAdditions)

- (NSString *)xpp_myLowerCaseString;

@end

@implementation NSString (XPPMyAdditions)

- (NSString *)xpp_myLowerCaseString
{
    NSString *LowerString = [self xpp_myLowerCaseString];
    NSLog(@"%@->%@", self, LowerString);
    return LowerString;
}

接下來做的就是把這個分類里面的方法和原生的方法交換一下:

void swizzling(){
    Method originalMtd = class_getInstanceMethod([UIF class], @selector(xpp_myLowerCaseString));
    Method swappedMtd = class_getInstanceMethod([NSString class], @selector(lowercaseString));
    method_exchangeImplementations(originalMtd, swappedMtd);

}

那么在以后,直接調用系統原生的lowercaseString方法時,實際上調用的是分類里面的方法,在達到原來目的的同時,還能輸出結果,非常方便!

注意:交換過后調用NSString原生的lowerCaseString實際上是調用xpp_myLowerCaseString;而在現在的xpp_myLowerCaseString里面,其實[self xpp_myLowerCaseString]實際上是調用了系統的lowerCaseString方法達到把字符串變為小寫的目的。所以,不會陷入死循環!

一次性更改

假如今天你接到產品的需求,把App里面所有的字體減小兩個點。你怎么辦?搜索找工程里面的systemFontOfSize:方法,挨個把字號-2;好,沒問題,可以。那第二天她覺得這個字太小了,再加1個點吧^?_?^。
這時候,方法交換技術派上用成了:

@interface UIFont (XppMyAdditions)

+ (UIFont *)xpp_systemFontOfSize:(CGFloat)size;

@end

@implementation UIFont (XppMyAdditions)

+ (UIFont *)xpp_systemFontOfSize:(CGFloat)size
{
    UIFont *font = [self xpp_systemFontOfSize:(size-2)];
    NSLog(@"%f---->%f",size, font.pointSize);
    return font;
}

接下來,再把系統的方法和該方法交換一下:

    Method m1 = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
    Method m2 = class_getClassMethod([UIFont class], @selector(xpp_systemFontOfSize:));
    method_exchangeImplementations(m1, m2);

注意:這里是類方法!不是實例方法,所以注意API的調用和分類方法要匹配,否則不會報錯,但是你會發現沒效果

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容