標籤:style blog color io os ar 使用 strong sp
C語言是靜態語言,它的工作方式是通過函數調用,這樣在編譯時間我們就已經確定程式怎樣執行的。而Objective-C是動態語言,它並不是通過調用類的方法來執行功能,而是給對象發送訊息,對象在接收到訊息之後會去找匹配的方法來執行。這樣的做法就把C語言在編譯時間的工作挪到了執行時來做,能夠獲得額外的靈活性。
在Objective-C中有個@selector,在非常多地方被翻譯成“選擇子”。實際上,對於類的執行個體對象來說,類的方法是用一個數字來代表的,並不是是我們看到的一個長長的帶著:這個字元的一串字串。通過這個@selector就能夠把這種方法的名字轉成所相應的數字。當一個類確定後,實際上每一個方法的@selector的值就是固定的,講到這裡,你一定能夠想到method swizzling是什麼一個東東了,沒錯,假設我們原來有個A方法,@selector(A)就是一個數字,我們的對象在接收到一個訊息後就去尋找相應的方法並執行——假設,我們把@selector(B)的數字換成了原來@selector(A)的數字,那麼此時對象儘管受到A訊息,但會去執行B方法!
在iOS中,這是全然能夠實現的,那麼我們什麼時候會須要這麼做呢?我認為有2個時候:
1. 破解,毋庸諱言,這絕對是破解的利器,不解釋了。
2. 在開發調試過程中,假設你對某個庫裡的方法不確定或者認為須要擴充的時候,你能夠自己寫一個去取代它。由於Objective-C是有Category的,所以擴充功能沒啥必要,但調試時添加?一些列印語句是非常方便實際的。
舉個範例,NSString裡面的lowercaseString方法,假設我不太清楚這種方法都幹了什麼,我就能夠自己寫個方法來替換它,這種方法裡面添加?列印語句,這樣log裡面就一目瞭然了。
首先須要添加?一個NSString的Category
@interface NSString (wzTest)- (NSString*)myLowerString;@end@implementation NSString (wzTest)- (NSString*)myLowerString{ NSString *lowerString = [self myLowerString]; NSLog(@"%@ => %@", self, lowerString); return lowerString;}@end 這裡有一個地方解釋一下,在myLowerString方法裡面,看起來遞迴調用了自身。可是,我們會用原來的lowercaseString方法去替換自己寫的myLowerString方法,所以這裡並沒有調用自身,而是調用了原來的lowercaseString方法。這點請注意一下。
其次替換系統原來的lowercaseString方法,使用runtime裡面的方法。
Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString)); Method swapMethod = class_getInstanceMethod([NSString class], @selector(myLowerString)); method_exchangeImplementations(originalMethod, swapMethod); NSString *testStr = @"thIs is THE Test STRING"; NSLog(@"lowerString of testStr=%@", [testStr lowercaseString]);
我們來看一下log的結果:
2014-05-29 22:17:55.514 testTableView[1582:a0b] thIs is THE Test STRING => this is the test string
2014-05-29 22:17:55.514 testTableView[1582:a0b] lowerString of testStr=this is the test string
我們能夠看到,系統中使用是繼續使用lowercaseString方法的,只是實際啟動並執行是我們新增的方法。當你不須要這樣做的時候,關閉method swizzling方法就能夠恢複了。
我們的範例中是添加?了列印語句,實際上還能夠做很多其它地操作。這在用第三方庫調試的時候是非常實用的一個方法,能夠非常方便的查看變數的內容或做一些其它工作。調試結束後,關閉method swizzling就能夠正常的工作。
iOS執行時與method swizzling