Method Swizzle黑魔法,修改 ios 系統類庫方法(轉載)

一般來說,系統提供的方法已經足夠開發了,但是有的時候有些需求用普通方法不好做。

如:在所有的viewcontroll 的viewwillappear:方法之前打個log

你可能會這么做:

1. 建一個uiviewcontroll 父類,重寫viewwillappear方法,調用super viewwillappear 方法之前加上log

2. 所有新建的uiviewcontroller 繼承第一步生成的

確實你是完成這樣的功能,可是你做了那么多的修改,基本每個uiviewcontroller都去修改了父類,這種方法太過于笨重了

?

本文提供了簡單地方法即可實現

我的理解中,object-c 的類調用方法是根據三個元素來定義的。?

1. 方法,代表類定義中一個方法類型(typedef struct objc_method *Method)

2. SEL 選擇器(typedef struct objc_selector *SEL),一個方法在運行時的名字,常見的有 [self performSelector:@selector(somemethod:) withObject:nil afterDelay:0.5]; @selector(somemethod:)作為方法的入口

3. 方法的實現入口(typedef id (*IMP)(id, SEL, …))

這三個元素確定了具體調用哪一個函數

?

直接看代碼

?

[objc]?view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. #import?"UIViewController+Tracking.h"??
  2. #import?<objc/runtime.h>??
  3. ??
  4. @implementation?UIViewController?(Tracking)??
  5. ??
  6. +?(void)load?{??
  7. ????NSString?*className?=?NSStringFromClass(self.class);??
  8. ????NSLog(@"classname?%@",?className);??
  9. ????static?dispatch_once_t?onceToken;??
  10. ????dispatch_once(&onceToken,?^{??
  11. ????????Class?class?=?[self?class];??
  12. ??????????
  13. ????????//?When?swizzling?a?class?method,?use?the?following:??
  14. ????????//?Class?class?=?object_getClass((id)self);??
  15. ??????????
  16. ????????SEL?originalSelector?=?@selector(viewWillAppear:);??
  17. ????????SEL?swizzledSelector?=?@selector(xxx_viewWillAppear:);??
  18. ??????????
  19. ????????Method?originalMethod?=?class_getInstanceMethod(class,?originalSelector);??
  20. ????????Method?swizzledMethod?=?class_getInstanceMethod(class,?swizzledSelector);??
  21. ??????????
  22. ????????BOOL?didAddMethod?=??
  23. ????????class_addMethod(class,??
  24. ????????????????????????originalSelector,??
  25. ????????????????????????method_getImplementation(swizzledMethod),??
  26. ????????????????????????method_getTypeEncoding(swizzledMethod));??
  27. ??????????
  28. ????????if?(didAddMethod)?{??
  29. ????????????class_replaceMethod(class,??
  30. ????????????????????????????????swizzledSelector,??
  31. ????????????????????????????????method_getImplementation(originalMethod),??
  32. ????????????????????????????????method_getTypeEncoding(originalMethod));??
  33. ????????}?else?{??
  34. ????????????method_exchangeImplementations(originalMethod,?swizzledMethod);??
  35. ????????}??
  36. ????});??
  37. }??

?

我們category重寫了NSObject的 load 方法oc提供了objc/runtime.h類讓我們獲取這些東西,同時還提供了對類方法操作的函數

我們想的是,直接用一個方法替換掉系統的方法,然后把一些自定義的動作加到方法中

我們只想運行一次就夠了,所以使用了 dispatch_once(&onceToken, ^{ …… }
接下來給類添加了新方法

把新方法和系統方法替換

?

?

[objc]?view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. #pragma?mark?-?Method?Swizzling??
  2. ??
  3. -?(void)xxx_viewWillAppear:(BOOL)animated?{??
  4. ????NSLog(@"viewWillAppear:?%@",?self);??
  5. ????[self?xxx_viewWillAppear:animated];??
  6. }??

但是新方法實現的時候,調用的是 [self xxx_viewwillAppear:animated]; 可能你會疑惑

?

這是因為我們在上面已經用xxx_viewwillAppear 和 viewwillAppear 互換了。所以實際上執行的是系統的viewwillAppear

這個時候可能你又有疑問了,為什么實現是- (void)xxx_viewWillAppear:(BOOL)animated{} 這樣的

這是因為 SEL swizzledSelector = @selector(xxx_viewWillAppear:); 拿的就是我們新寫的方法。

可以結合這篇博客看,配圖很容易懂

http://blog.csdn.net/yiyaaixuexi/article/details/9374411

?

以及這篇對SEL講的比較清楚

http://blog.csdn.net/fengsh998/article/details/8612969

代碼下載地址

https://github.com/holysin/Method_swizzle

1 ?Method?nameMethod =?class_getInstanceMethod(Class class,SEL name);//得到實例方法

參數:class類名 ?name 方法名

理解:通過類名和方法名來得到方法(c函數)

?

2 method_getImplementation(Method method)

參數:method 方法

理解:通過方法來得到它的實現

?

?

3 BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

理解:將所給的name(方法名)的方法實現,被imp(方法的實現)代替

cls:被添加方法的類

name:可以理解為方法名,這個貌似隨便起名,

imp:實現這個方法的函數?

types:一個定義該函數返回值類型和參數類型的字符串,這個具體會在后面講

?

4 class_replaceMethod(Class class,SEL ?B,?method_getImplementation(Method AMethod),?method_getTypeEncoding(Method AMethod));

參數:class :方法所屬的類 B:將被替換其實現的方法名 ? ?AMethod:由A生成的方法(c函數)

理解:用A的方法實現來代替B的方法實現

5 method_exchangeImplementations(SEL A, SEL B);

理解:交換兩個方法的實現

void swizzle_method(Class class,SEL originalSelector,SEL swizzledSelector) {

? ? Method originalMethod = class_getInstanceMethod(class, originalSelector);//得到實例方法

? ? Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

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

? ? if (didSwizzleMethod) {

? ? ? ? class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

? ? } else {

? ? ? ? method_exchangeImplementations(originalMethod, swizzledMethod);

? ? }

}

?

?

轉載于:https://www.cnblogs.com/HughLiu/p/4648105.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375731.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375731.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375731.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

win10無法開啟夜間模式

在學校的時候沒感覺&#xff0c;一進公司發現電腦還是需要設置一下護眼的&#xff0c;但是在設置的時候卻遇到夜間模式無法開啟的問題。 首先在左下角搜索設備管理器 找到顯示適配器 查看顯示器設備狀態 如果設備圖標上有黃三角感嘆號則說明該設備驅動有問題&#xff0c;需要…

Linux LVM學習總結——擴展卷組VG

Linux服務器由于應用變更或需求的緣故&#xff0c;有可能出現分區空間不足的情況&#xff0c;此時往往需要進行擴容&#xff08;要增加分區的空間&#xff09;&#xff0c;而采用LVM的好處就是可以在不需停機的情況下可以方便地調整各個分區大小。如下所示&#xff0c;分區/u05…

【液晶模塊系列基礎視頻】1.3.iM_TFT30模塊簡介

【液晶模塊系列基礎視頻】1.3.iM_TFT30模塊介紹 技術論壇&#xff1a;http://www.eeschool.org 博客地址&#xff1a;http://xiaomagee.cnblogs.com 官方網店&#xff1a;http://i-board.taobao.com 銀杏科技 GINGKO TECH. 保留權利&#xff0c;轉載請注明出處 本次教學視頻介…

C++控制向文件中寫入浮點數的格式

有時會遇到向文件中寫入一定格式的浮點數&#xff0c;為了對齊美觀&#xff0c;常常采用控制小數點后的位數并用0補齊缺少的位數的方法。 #include <iostream> #include <iomanip> #include <fstream> using namespace std;int main(){double pi3.14;ofstre…

項目管理工具到底應該為誰服務?

項目管理工具到底應該為誰服務&#xff1f;為管理者&#xff0c;還是為了團隊&#xff1b;為了管理報表&#xff0c;還是為了協作需求&#xff0c;這些是在項目管理工具選擇或開發時需要面對和思考的一個問題。 傳統項目管理工具在團隊內部臭名昭著 項目管理工具當初都是為了項…

二叉樹的遞歸定義及存儲

定義 最多有兩棵子樹的有序樹&#xff0c;稱為二叉樹。二叉樹是一種特殊的樹。 遞歸定義&#xff1a;二叉樹是n(n>0)個有限結點構成的集合。N0稱為空二叉樹&#xff1b;n>0的二叉樹由一個根結點和兩互不相交的&#xff0c;分別稱為左子樹和右子樹的二叉樹構成。 二叉樹中…

C++統計微妙級時間消耗(chrono)

有時我們需要統計某段程序運行所消耗的時間&#xff0c;通過C的chrono庫&#xff0c;我們可以輕松實現這一需求&#xff0c;例如&#xff0c;我們求斐波那契數列消耗的時間。 #include <iostream> #include <chrono> #include <iomanip> using namespace st…

content-length與Transfer-Encoding: chunked的問題釋疑

content-length與Transfer-Encoding: chunked的問題釋疑 http返回頭中content-length與Transfer-Encoding: chunked的問題釋疑 先說說問題出現的背景&#xff1a; 公司服務器與手機客戶端交互&#xff0c;客戶端請求一個動態生成的XML文件&#xff0c;在用firebug查看http響應頭…

基于RSA的加密/解密示例C#代碼

在C#程序中&#xff0c;大家可能比較熟悉的方式是md5加密解密方式&#xff0c;對RSA可能并不是很熟悉&#xff0c; 下面就說一下RSA加密和解密的算法&#xff1a;using System;using System.Security.Cryptography;using System.Text;class RSACSPSample{static void Main(){tr…

iOS GorupBy

轉自&#xff1a; IOS 數組分組 Grouped NSArray 12345678NSMutableSet *set[NSMutableSet set];[_list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {[set addObject:obj["MeasureType"]];//利用set不重復的特性,得到有多少組,根據數組中的…

android通過adb shell播放音樂

am start -n com.android.music/com.android.music.MediaPlaybackActivity -d /sdcard/timian.mp3拓展閱讀 input keyevent 24 #增加音量 input keyevent 25 #降低音量 input keyevent 85 #暫停/播放 input keyevent 126 #恢復播放 input keyevent 127 #停止播放關閉音樂播放器…

NetBpm 安裝篇(1)

尊重別人勞動成果 轉載注明出處&#xff1a;http://www.cnblogs.com/anbylau2130/p/3875718.html 官方主頁 http://www.netbpm.org/docs/install.html 文件目錄 Netbpm的兩種服務器配置 1&#xff0c;CassiniWebServer CassiniWebServer.exe是輕量級的web服務器&#xff0c;相…

python將文本中的數據處理成圖像(matplotlib)

使用Python的matplotlib模塊可以很方便的將數據處理成圖表&#xff0c;使數據更加形象、直觀。 #!/usr/bin/env pythonimport matplotlib.pyplot as plt import numpy as np from mpl_toolkits.axes_grid.anchored_artists import AnchoredTexty1np.loadtxt(ReadDataCostTime.…

string 中的 length函數 和size函數 返回值問題

string 中的 length函數 和 size函數 的返回值 ( 還有 char [ ] 中 測量字符串的 strlen 函數 ) 應該是 unsigned int 類型的 不可以 和 -1 比較。 應盡量避免 unsigned int 類型 和 int類型 數據 的比較 。當unsigned int 類型 和 int類型 數據 比較 時 &#xff0c;會 把…

交叉編譯android版htop

編這個東西賊煩人。 話不多說&#xff0c;直接上教程 源代碼版本&#xff1a;htop-2.2.0、ncurses-6.1 編譯之前要確認自己有ndk&#xff0c;從【官網】直接下載&#xff0c;下載下來解壓一下就能用。 先編ncurses 編譯過程 ./configure CCarm-linux-androideabi-gcc-4.9 \-…

今天的一點點收獲

今天怎么說呢&#xff0c;還是有點收獲的&#xff0c;上午寫了一上午的前端&#xff0c;然后就是下午又是一下午的c#&#xff0c;好特么酸爽啊&#xff0c;但是有一件特別蛋疼的事情發生了&#xff0c;我 天天叫的學長竟然不是學長而是學校的而老師&#xff0c;但是他們都不叫他…

jquery動態添加刪除div--事件綁定,對象克隆

我想做一個可以動態添加刪除div的功能。中間遇到一個問題&#xff0c;最后在manong123.com開發文摘 版主的熱心幫助下解答了(答案在最后) 使用到的jquery方法和思想就是&#xff1a;事件的綁定和銷毀(unbind)&#xff0c;另外還可以使用clone,通過克隆可以很好的解決這個問…

編程知識大雜燴

以下資料完全是隨手記錄&#xff0c;沒有任何順序或關聯&#xff0c;需要用直接^F找就行了。 1. ps aux指令詳解 http://blog.csdn.net/hanner_cheung/article/details/6081440 2. Linux下配置Apache php http://lelong.iteye.com/blog/904125 3. shell定義變量 http://see.xid…

最長公共前綴

2、最長公共前綴 編寫一個函數來查找字符串數組中的最長公共前綴。 如果不存在公共前綴&#xff0c;返回空字符串 “”。 示例1 輸入: ["flower","flow","flight"] 輸出: "fl"示例2 輸入: ["dog","racecar",…