Method Swizzling

Swizzling 的應(yīng)用場景:
1)比如需要統(tǒng)計在每個界面停留時間屎媳。我們需要在

  • (void)viewWillAppear:(BOOL)animated;
  • (void)viewDidAppear:(BOOL)animated;
    兩個方法中寫上統(tǒng)計用的方法环葵,但是按照常規(guī)的方法颗品,需要在每個界面加上統(tǒng)計代碼火本,這樣不僅繁瑣而且很有可能落掉一些頁面(這個時候你可能想使用基類沦童,但是很多項目并沒有繼承統(tǒng)一的一個或者幾個基類)允懂,所以這個時候就需要使用黑魔法 Swizzling空骚。

2)還可以用來打印每個頁面的類名巷送,這樣當你接手一個新項目的時候驶忌,可以使用Swizzling來打印出每個控制器的名稱,這樣就很容易的弄清項目的架構(gòu)笑跛。

先看一段代碼:

#import <objc/runtime.h>

@implementation UIViewController (Tracking)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(xxx_viewWillAppear:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(class, originalSelector);
        // Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

        BOOL didAddMethod =
            class_addMethod(class,
                originalSelector,
                method_getImplementation(swizzledMethod),
                method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                swizzledSelector,
                method_getImplementation(originalMethod),
                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling

- (void)xxx_viewWillAppear:(BOOL)animated {
    [self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}

@end

先來看代碼解釋:

1)+(void)load 和 +(void)initialize的區(qū)別

//Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
//A class’s +load method is called after all of its superclasses’ +load methods.
//A category +load method is called after the class’s own +load method.
+(void)load
在Objective-C運行時載入類或者Category時被調(diào)用,這個方法對動態(tài)庫和靜態(tài)庫中的類或(Category)都有效.

//initialize is invoked only once per class. If you want to perform independent initialization for the class and for categories of the class, you should implement load methods.
+(void)initialize

+(void)initialize 會在運行時僅被觸發(fā)一次付魔,如果沒有向類發(fā)送消息的話,這個方法將不會被調(diào)用飞蹂。這個方法的調(diào)用是線程安全的抒抬。父類會比子類先收到此消息。

要點:
1晤柄、initialize和load擦剑,我們并不需要在這兩個方法的實現(xiàn)中使用super調(diào)用父類的方法妖胀。
2、load和initialize被調(diào)用一次是相對runtime而言 惠勒,你可以當作普通類方法多次調(diào)用赚抡。
3、類加載到系統(tǒng)的時候就用調(diào)用load方法纠屋,類首次使用的時候調(diào)用initialize方法涂臣。
4、load不像普通方法一樣遵從那套繼承規(guī)則售担,當每個類沒有實現(xiàn) load方法赁遗,不管各級超類是否實現(xiàn),系統(tǒng)都不會調(diào)用此類的load方法族铆。initialize與其他方法一樣岩四,如果每個類沒有實現(xiàn)initialize方法,而超類實現(xiàn)了哥攘,那么就會執(zhí)行超類的這個方法剖煌,所以通常會:
5、initialize和load的方法必須寫的精簡逝淹。
6耕姊、initialize中可以實現(xiàn)無法在編譯期初始化的全局變量,load的方法中可以實現(xiàn)swizzling的邏輯栅葡。
7茉兰、load的調(diào)用并不視為類的第一個方法完成,因為load中調(diào)用了當前類中的方法欣簇,就先去執(zhí)行initialize方法了规脸。
8、Runtime調(diào)用+(void)load時沒有autorelease pool
9醉蚁、load方法調(diào)用的順序:父類(Superclass)的方法優(yōu)先于子類(Subclass)的方法燃辖,類中的方法優(yōu)先于類別(Category)中的方法。
10网棍、所有類別(Category)中的load方法都會執(zhí)行黔龟。
11、最后一個類別(Category)中的initialize方法會覆蓋之前類別和類中的initialize方法滥玷。

2)dispatch_once
由于swizzling會改變?nèi)譅顟B(tài)氏身,所以我們使用的時候需要加倍小心,所以在運行時中加上 dispatch_once惑畴,
它確保代碼即使在多線程環(huán)境下也只會被執(zhí)行一次蛋欣。

3) SEL, Method如贷,IMP
SEL:SEL是一個方法在運行時的名字陷虎,OC中調(diào)用一個方法到踏,就是向?qū)ο蟀l(fā)送一個消息,通過SEL找到這個方法尚猿。

Method:

IMP:IMP就是方法的實現(xiàn)

Method swizzling 就是通過交換方法的實現(xiàn)

//Returns the implementation of a method. A function pointer of type IMP.
method_getImplementation

//Replaces the implementation of a method for a given class.The previous implementation of the method identified by name for the class identified by cls.
class_replaceMethod

//Exchanges the implementations of two methods.
method_exchangeImplementations

4) 在交換的方法里面實現(xiàn)自己的目的

- (void)xxx_viewWillAppear:(BOOL)animated
 {    
    [self xxx_viewWillAppear:animated];     
    NSLog(@"viewWillAppear: %@", NSStringFromClass([self class])); 
}

[self xxx_viewWillAppear:animated]; 在方法里面調(diào)用不會引起循環(huán)調(diào)用窝稿,因為這個是運行時已經(jīng)把xxx_viewWillAppear和viewWillAppear調(diào)換,調(diào)用viewWillApper是遵循調(diào)用父類的規(guī)則凿掂,避免出現(xiàn)意想不到的問題伴榔。

-(BOOL) isKindOfClass: classObj 判斷是否是這個類,包括這個類的子類和父類的實例庄萎;
-(BOOL) isMemberOfClass: classObj 判斷是否是這個類的實例,不包括子類或者父類踪少;

參考原文地址:
http://nshipster.com/method-swizzling/
參考文獻:
http://justsee.iteye.com/blog/1630979

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糠涛,隨后出現(xiàn)的幾起案子援奢,更是在濱河造成了極大的恐慌,老刑警劉巖脱羡,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萝究,死亡現(xiàn)場離奇詭異免都,居然都是意外死亡锉罐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門绕娘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脓规,“玉大人,你說我怎么就攤上這事险领∏扔撸” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵绢陌,是天一觀的道長挨下。 經(jīng)常有香客問我,道長脐湾,這世上最難降的妖魔是什么臭笆? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮秤掌,結(jié)果婚禮上愁铺,老公的妹妹穿的比我還像新娘。我一直安慰自己闻鉴,他們只是感情好茵乱,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孟岛,像睡著了一般瓶竭。 火紅的嫁衣襯著肌膚如雪督勺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天斤贰,我揣著相機與錄音玷氏,去河邊找鬼。 笑死腋舌,一個胖子當著我的面吹牛盏触,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播块饺,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼赞辩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了授艰?” 一聲冷哼從身側(cè)響起辨嗽,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淮腾,沒想到半個月后糟需,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡谷朝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年洲押,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片圆凰。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡杈帐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出专钉,到底是詐尸還是另有隱情挑童,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布跃须,位于F島的核電站站叼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏菇民。R本人自食惡果不足惜尽楔,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玉雾。 院中可真熱鬧翔试,春花似錦、人聲如沸复旬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驹碍。三九已至壁涎,卻和暖如春凡恍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怔球。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工嚼酝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人竟坛。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓闽巩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親担汤。 傳聞我的和親對象是個殘疾皇子涎跨,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,682評論 0 9
  • 得承認崭歧,每每看到別人聲稱 method swizzling是一個多么強大的工具隅很,我就很納悶,這工具的應(yīng)用場景有哪些...
    seedante閱讀 525評論 0 2
  • 轉(zhuǎn)載:http://www.cocoachina.com/ios/20161102/17920.html 因為Ob...
    F麥子閱讀 664評論 0 1
  • 一率碾、Method Swizzling 原理 我們知道 OC 是動態(tài)語言叔营,我們執(zhí)行一個函數(shù)的時候,其實是在發(fā)一條消息...
    Cheriez閱讀 389評論 0 0
  • 時光靜寂所宰,歲月輕柔绒尊,拈一顆素心,輕倚季節(jié)的轉(zhuǎn)角歧匈,看流年的風(fēng)輕輕吹過垒酬,始終相信砰嘁,時光可以帶走最美的年華件炉,歲月可以刻畫...
    紅塵莫笑人閱讀 422評論 0 1