關(guān)于Method Swizzling

下午接到一個(gè)有趣的問(wèn)題:
問(wèn)這種情況要怎么處理授滓?

看到這個(gè)問(wèn)題的第一想法就是利用runtime的方法交換琳水,通過(guò)自己的方法替換系統(tǒng)方法,在自己的方法里面添加判斷褒墨。
  當(dāng)列表滑動(dòng)的時(shí)候會(huì)去調(diào)用scrollViewDidScroll這個(gè)代理方法炫刷,需求實(shí)現(xiàn)的切入點(diǎn)應(yīng)該就是這里。但是Method Swizzling方法只能替換類本身的方法郁妈,對(duì)于delegate這種虛函數(shù)一樣的東西就無(wú)從下手了。所以Method Swizzling就暫且放在一邊绍申,那通過(guò)kvo呢噩咪?在擴(kuò)展里面去監(jiān)聽(tīng)某個(gè)變化的值?scrollView剛好有個(gè)contentOffset符合要求极阅,但是kvo是不能寫(xiě)在+ (void)load方法里面的胃碾,這時(shí)候靈光一閃,我們可以用Method Swizzling來(lái)替換contentOffsetset方法敖畈仆百!

思路有了,那就上代碼:
#import "UIScrollView+Additions.h"
#import <objc/runtime.h>

@implementation UIScrollView (Additions)

+ (void)load {
   Method contentOffsetMethod = class_getInstanceMethod([UIScrollView class], @selector(setContentOffset:));

    Method class_contentOffsetMethod = class_getInstanceMethod([UIScrollView class], @selector(class_setContentOffset:));

    method_exchangeImplementations(contentOffsetMethod, class_contentOffsetMethod);
}

-(void)class_setContentOffset:(CGPoint)contentOffset{
    if (contentOffset.y > self.bounds.size.height) {
        NSLog(@"change sucess!");
    } else {
        NSLog(@"change fail!");
    }
    [self class_setContentOffset:contentOffset];
}
@end

運(yùn)行效果如下:


image.png

沒(méi)毛病~

干貨: Method Swizzling

這種我們既不需要源代碼奔脐,也不需要通過(guò)繼承子類類覆寫(xiě)方法就能改變這個(gè)類本身功能的方案被稱為——方法調(diào)配(method swizzling)
類的方案列表會(huì)把選擇子的名稱映射到相關(guān)方法的實(shí)現(xiàn)之上俄周,是的“動(dòng)態(tài)消息派發(fā)系統(tǒng)”能夠根據(jù)此找到應(yīng)該調(diào)用的方法。這些方法均以函數(shù)指針的形式來(lái)表示髓迎,這種指針叫做IMP峦朗。原型如下:

  id (*IMP)(ID,SEL,...)

NSString類可以相應(yīng)lowercaseString,uppercaseString,capitalizedString等選擇子。這張映射表中的每個(gè)選擇子都映射到了不同的IMP之上排龄,如圖:

image.png

runtime運(yùn)行時(shí)提供的幾個(gè)方法都能來(lái)操作這張表波势。deveolper可以向其中新增selector,也可以改變某個(gè)selector對(duì)應(yīng)的方法實(shí)現(xiàn)橄维,還可以交換兩個(gè)selector所映射到的指針尺铣。經(jīng)過(guò)幾次操作之后,類的方法表就會(huì)變成下圖的樣子:

image.png

在新的映射表中争舞,多了一個(gè)名為newSelectorselector,capitalizedString的實(shí)現(xiàn)也變了凛忿,而lowercaseStringuppercaseString的實(shí)現(xiàn)則互相轉(zhuǎn)換了。上述修改均無(wú)需編寫(xiě)子類兑障,只要修改了“方法表”的布局侄非,就會(huì)反映到程序中所有的NSString實(shí)例指向蕉汪。這下大家見(jiàn)識(shí)到此特性的強(qiáng)大之處了吧?
  本條將會(huì)談到如何互換兩個(gè)方法實(shí)現(xiàn)逞怨。通過(guò)此操作者疤,可為已有的方法添加新功能。不過(guò)在講解怎樣添加新功能之前叠赦,我們先來(lái)看看怎樣互換兩個(gè)已經(jīng)寫(xiě)好的方法實(shí)現(xiàn)驹马。想交換方法實(shí)現(xiàn),可用下列函數(shù):

void method_exchangeImplementations(Method m1, Method m2)

此函數(shù)的兩個(gè)參數(shù)表示待交換的兩個(gè)方法實(shí)現(xiàn)除秀,而方法實(shí)現(xiàn)則可通過(guò)下列函數(shù)獲得:

//得到類的實(shí)例方法(-號(hào)方法)
Method class_getInstanceMethod(Class aClass, SEL aSelector)
//得到類的類方法(+號(hào)方法)
 Method class_getInstanceMethod(Class aClass, SEL aSelector)

此函數(shù)根據(jù)給定的選擇從類中取出與之相關(guān)的方法糯累。會(huì)執(zhí)行下列代碼,即可交換前面提到的兩個(gè)方法實(shí)現(xiàn):

  Method contentOffsetMethod = class_getInstanceMethod([UIScrollView class], @selector(setContentOffset:));

  Method class_contentOffsetMethod = class_getInstanceMethod([UIScrollView class], @selector(class_setContentOffset:));

  method_exchangeImplementations(contentOffsetMethod, class_contentOffsetMethod);

從現(xiàn)在開(kāi)始册踩,如果UIScrollView上調(diào)用了setContentOffset:泳姐,那么將會(huì)執(zhí)行class_contentOffsetMethod:的方法實(shí)現(xiàn)。然后我們可以在class_contentOffsetMethod方法里面去實(shí)現(xiàn)所需的附加功能暂吉,并調(diào)用原有實(shí)現(xiàn)胖秒。

-(void)class_setContentOffset:(CGPoint)contentOffset{
    NSLog(@"這里調(diào)用的先后順序?慕的?");
    if (contentOffset.y > self.bounds.size.height) {
        NSLog(@"change sucess!");
    } else {
        NSLog(@"change fail!");
    }
    [self class_setContentOffset:contentOffset];
}

這段代碼看上去好像會(huì)陷入遞歸調(diào)用的死循環(huán)阎肝,不過(guò)請(qǐng)記住,此方法是準(zhǔn)備和setContentOffset:方法互換的肮街。所以在運(yùn)行時(shí)风题,class_setContentOffset:實(shí)際上對(duì)應(yīng)的是setContentOffset:方法實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嫉父,一起剝皮案震驚了整個(gè)濱河市沛硅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌熔号,老刑警劉巖稽鞭,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異引镊,居然都是意外死亡朦蕴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)弟头,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吩抓,“玉大人,你說(shuō)我怎么就攤上這事赴恨≌钊ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵伦连,是天一觀的道長(zhǎng)雨饺。 經(jīng)常有香客問(wèn)我钳垮,道長(zhǎng),這世上最難降的妖魔是什么额港? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任饺窿,我火速辦了婚禮,結(jié)果婚禮上移斩,老公的妹妹穿的比我還像新娘肚医。我一直安慰自己,他們只是感情好向瓷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布肠套。 她就那樣靜靜地躺著,像睡著了一般猖任。 火紅的嫁衣襯著肌膚如雪你稚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天超升,我揣著相機(jī)與錄音入宦,去河邊找鬼。 笑死室琢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的落追。 我是一名探鬼主播盈滴,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轿钠!你這毒婦竟也來(lái)了巢钓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疗垛,失蹤者是張志新(化名)和其女友劉穎症汹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贷腕,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡背镇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泽裳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞒斩。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涮总,靈堂內(nèi)的尸體忽然破棺而出胸囱,到底是詐尸還是另有隱情,我是刑警寧澤瀑梗,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布烹笔,位于F島的核電站裳扯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谤职。R本人自食惡果不足惜饰豺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柬帕。 院中可真熱鬧哟忍,春花似錦、人聲如沸陷寝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)凤跑。三九已至爆安,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仔引,已是汗流浹背扔仓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咖耘,地道東北人翘簇。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像儿倒,于是被迫代替她去往敵國(guó)和親版保。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉夫否,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,690評(píng)論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,548評(píng)論 33 466
  • 繼上Runtime梳理(四) 通過(guò)前面的學(xué)習(xí)彻犁,我們了解到Objective-C的動(dòng)態(tài)特性:Objective-C不...
    小名一峰閱讀 744評(píng)論 0 3
  • 我們常常會(huì)聽(tīng)說(shuō) Objective-C 是一門(mén)動(dòng)態(tài)語(yǔ)言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢凰慈?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,182評(píng)論 0 7
  • 文中的實(shí)驗(yàn)代碼我放在了這個(gè)項(xiàng)目中汞幢。 以下內(nèi)容是我通過(guò)整理[這篇博客] (http://yulingtianxia....
    茗涙閱讀 914評(píng)論 0 6