亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

IOS Object-C 中Runtime詳解及實例代碼

2020-07-26 02:54:23
字體:
來源:轉載
供稿:網友

IOS Object-C 中Runtime詳解

最近了解了一下OC的Runtime,真的是OC中很強大的一個機制,看起來比較底層,但其實可以有很多活用的方式。

什么是Runtime

我們雖然是用Objective-C寫的代碼,其實在運行過程中都會被轉化成C代碼去執行。比如說OC的方法調用都會轉成C函數 id objc_msgSend ( id self, SEL op, … ); 而OC中的對象其實在Runtime中都會用結構體來表示,這個結構體中包含了類名、成員變量列表、方法列表、協議列表、緩存等。

類在Runtime中的表示:

struct objc_class { Class isa;//指針,顧名思義,表示是一個什么, //實例的isa指向類對象,類對象的isa指向元類#if !__OBJC2__ Class super_class; //指向父類 const char *name; //類名 long version; long info; long instance_size struct objc_ivar_list *ivars //成員變量列表 struct objc_method_list **methodLists; //方法列表 struct objc_cache *cache;//緩存 //一種優化,調用過的方法存入緩存列表,下次調用先找緩存 struct objc_protocol_list *protocols //協議列表 #endif} OBJC2_UNAVAILABLE;/* Use `Class` instead of `struct objc_class *` */

整個Runtime機制其實可以挖的點很多,這里只是簡單的介紹一些常見的用法,如果將其細細解析,相信一定會對OC的理解加深幾個層面。

獲取屬性/方法/協議列表

最直接的一種用法,就是獲取我們的結構體中存儲的對象的屬性、方法、協議等列表,從而獲取其所有這些信息。

要獲取也比較簡單,但是自己嘗試之前需要注意幾點:

一定要自己給類加幾個屬性、方法,遵循一些協議,否則當然是看不到輸出信息的。

要使用這些獲取的方法,需要導入頭文件 #import

#import <objc/runtime.h>// 輸出類的一些信息- (void)logInfo { unsigned int count;// 用于記錄列表內的數量,進行循環輸出 // 獲取屬性列表 objc_property_t *propertyList = class_copyPropertyList([self class], &count); for (unsigned int i = 0; i < count; i++) { const char *propertyName = property_getName(propertyList[i]); NSLog(@"property --> %@", [NSString stringWithUTF8String:propertyName]); } // 獲取方法列表 Method *methodList = class_copyMethodList([self class], &count); for (unsigned int i; i < count; i++) { Method method = methodList[i]; NSLog(@"method --> %@", NSStringFromSelector(method_getName(method))); } // 獲取成員變量列表 Ivar *ivarList = class_copyIvarList([self class], &count); for (unsigned int i; i < count; i++) { Ivar myIvar = ivarList[i]; const char *ivarName = ivar_getName(myIvar); NSLog(@"Ivar --> %@", [NSString stringWithUTF8String:ivarName]); } // 獲取協議列表 __unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count); for (unsigned int i; i < count; i++) { Protocol *myProtocal = protocolList[i]; const char *protocolName = protocol_getName(myProtocal); NSLog(@"protocol --> %@", [NSString stringWithUTF8String:protocolName]); }}

方法調用的過程

調用方法分為調用實例方法和調用類方法,在結構體我們可以看到第一個就是一個 isa 指針,會指向類對象或者元類,什么叫元類呢?

每個實例對象有個isa的指針,他指向對象的類,而類里也有個isa的指針, 指向meteClass(元類)。元類保存了類方法的列表。當類方法被調用時,先會從本身查找類方法的實現,如果沒有,元類會向他父類查找該方法。同時注意的是:元類(meteClass)也是類,它也是對象。元類也有isa指針,它的isa指針最終指向的是一個根元類(root meteClass)。根元類的isa指針指向本身,這樣形成了一個封閉的內循環。

通過isa,就可以不斷往上方去回溯自己的父類等,而方法的調用也利用了這個過程:

  1. 首先,當然在對象自己緩存的方法列表中去找要調用的方法,找到了就直接執行其實現。
  2. 緩存里沒找到,就去上面說的它的方法列表里找,找到了就執行其實現。
  3. 還沒找到,說明這個類自己沒有了,就會通過isa去向其父類里執行1、2。
  4. 如果找到了根類還沒找到,那么就是沒有了,會轉向一個攔截調用的方法,我們可以自己在攔截調用方法里面做一些處理。
  5. 如果沒有在攔截調用里做處理,那么就會報錯崩潰。

以上就是方法調用的過程。我們可以看到的是,所謂重寫父類方法,并不是抹除了父類方法,父類的方法還是存在的,只是我們在子類里面找到了就不會再去父類里找了,是這個層面的“覆蓋”。而我們熟悉的 super 調用父類的方法實現,就是告知要去調用父類實現的標識。

攔截調用與動態添加

上面說到了攔截調用,就是在所有地方都找不到方法的實現的話,會出發攔截調用,可以自己去做一些處理避免程序崩潰。那在什么地方做處理呢?NSObject有四個方法可以用來做處理:

// 調用不存在的類方法時觸發,默認返回NO,可以加上自己的處理后返回YES+ (BOOL)resolveClassMethod:(SEL)sel;// 調用不存在的實例方法時觸發,默認返回NO,可以加上自己的處理后返回YES+ (BOOL)resolveInstanceMethod:(SEL)sel;// 將調用的不存在的方法重定向到一個其他聲明了這個方法的類里去,返回那個類的target- (id)forwardingTargetForSelector:(SEL)aSelector;// 將調用的不存在的方法打包成 NSInvocation 給你,自己處理后調用 invokeWithTarget: 方法讓某個類來觸發- (void)forwardInvocation:(NSInvocation *)anInvocation;

假設我們成功攔截下來了,那我們可以做什么處理呢?這個其實就是根據具體情況看你要怎么處理了。但這里有一個久聞其名的東西就可以派上用場了:動態添加方法。

我們知道OC是動態的,也就是說很多東西它不是在編譯時去判斷,而是在運行時去處理的,這其實帶來了很大的靈活性,比如這里我們對于一些不存在的方法的調用,就可以動態去添加上一個方法來代替我們要調用的方法。

比如我們添加一個Button,點擊事件我們關聯到一個沒有具體實現的實例方法,這種情況下如果不做任何處理那么點擊Button后一定會崩潰,但是如果我們攔截并動態添加一個方法來報警,就不會崩潰了:

@interface ViewController ()@property (nonatomic, strong) UIButton *logBtn;- (void)notHas;// 要調用的實例方法,沒有具體實現@end- (void)viewDidLoad { [super viewDidLoad]; // 添加按鈕 self.logBtn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 100, 20)]; [self.logBtn setTitle:@"測 試" forState:UIControlStateNormal]; [self.logBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; // 添加沒有實現的點擊事件 [self.logBtn addTarget:self action:@selector(notHas) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.logBtn];}// 攔截對不存在的方法的調用+ (BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"notFind!"); // 給本類動態添加一個方法 if ([NSStringFromSelector(sel) isEqualToString:@"notHas"]) { class_addMethod(self, sel, (IMP)runAddMethod, "v@:*"); } // 注意要返回YES return YES;}// 要動態添加的方法,這是一個C方法 void runAddMethod(id self, SEL _cmd, NSString *string) { NSLog(@"動態添加一個方法來提示");}

按照上面的處理,點擊按鈕后就不會崩潰,而是轉到了對 runAddMethod 方法的調用。其實更明確地說,應該是重現了對要調用的方法的實現,將原本要調用的方法的實現,改為了一個新的實現。class_addMethod 方法的第二個參數是要重寫的方法,這里用的就是傳進來的參數sel,第三個參數就是重寫后的實現。第四個參數是方法的簽名。

關聯對象

什么叫關聯對象?說通俗一點,我們都知道用Category類別可以給一些已經存在的,比如系統的類添加方法,但是不能添加新屬性,那怎么添加屬性呢?一種直接的方法是繼承,但如果只是為了添加一個屬性就去做一次繼承,還是有點重,這時候,就可以用關聯對象的方法。

有兩個相關的方法:

objc_setAssociatedObject 方法用來給類關聯一個屬性;
objc_getAssociatedObject 方法用來獲取之前關聯的屬性。

比如說給自己這個類關聯一個字符串:

 // 關聯對象 static char associatedObjectKey; objc_setAssociatedObject(self, &associatedObjectKey, @"我就是要關聯的字符串對象內容", OBJC_ASSOCIATION_RETAIN_NONATOMIC); NSString *theString = objc_getAssociatedObject(self, &associatedObjectKey); NSLog(@"關聯對象:%@", theString);

我們先給self關聯了一個字符串內容,然后通過get方法獲取了關聯的字符串內容,并輸出。

從代碼中其實也可以猜到各個參數的意思,self的參數就是要處理的類;associatedObjectKey 的參數其實就類似于key,用來標識區分你要關聯的這個對象;第三個參數是要關聯的對象;第四個參數是關聯的策略,用命名就可以看出來全是在添加@property屬性時用到的一些修飾符,有五種策略:

enum { OBJC_ASSOCIATION_ASSIGN = 0, OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,  OBJC_ASSOCIATION_COPY_NONATOMIC = 3, OBJC_ASSOCIATION_RETAIN = 01401, OBJC_ASSOCIATION_COPY = 01403 };

熟悉@property屬性修飾符的應該能直接明白了,不熟悉的可以看這篇文章:傳送門:iOS中assign、retain、copy、weak、strong的區別以及nonatomic的含義

當然,你也可以和類別一起用,創建兩個方法用來關聯和獲取對象,比如下面這樣:

//添加關聯對象- (void)addAssociatedObject:(id)object{ objc_setAssociatedObject(self, @selector(getAssociatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}//獲取關聯對象- (id)getAssociatedObject{ return objc_getAssociatedObject(self, _cmd);}

這樣就既能通過Category類別來添加方法,用一起順便提供了對屬性的添加了。

以上是對Runtime的一點淺薄的理解和使用,Runtime的天地應該是很廣闊的,也能挖出很多高級的使用方法來,對于理解OC的運行機制是很有幫助的。

源碼下載:http://xiazai.VeVB.COm/201703/yuanma/RuntimeDemo-master(VeVB.COm).rar

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久频这里精品99香蕉| 日韩亚洲成人av在线| 亚洲天堂精品在线| 日韩中文字幕视频在线观看| 韩国精品美女www爽爽爽视频| 都市激情亚洲色图| 91精品国产91久久久久久| 久久免费精品视频| 亚洲精品国产福利| 欧美激情videos| 2019精品视频| 亚洲成人999| 国产在线观看精品一区二区三区| 亚洲三级 欧美三级| 欧美日韩另类在线| 欧美激情一区二区三区在线视频观看| 欧美高清视频一区二区| 欧美在线视频播放| 亚洲精品不卡在线| 色婷婷综合久久久久中文字幕1| 日本中文字幕成人| 精品人伦一区二区三区蜜桃免费| 亚洲xxxx在线| 日韩美女福利视频| 日韩在线观看电影| 国产精品成熟老女人| 亚洲图片欧美午夜| 69久久夜色精品国产69乱青草| 亚洲国产日韩欧美在线99| 97超碰色婷婷| 少妇高潮久久久久久潘金莲| 国产成人在线一区| 久久精品一区中文字幕| 91久久久久久久久| 最近2019中文字幕mv免费看| 久久国产精品久久久久| 国产91精品久久久久| 久久久久久久久久亚洲| 成人免费观看49www在线观看| 亚洲最大激情中文字幕| 在线观看免费高清视频97| 亚洲欧美激情另类校园| 欧美一区二区.| 成人美女av在线直播| 亚洲黄色www| 国产成人精品在线视频| 欧美一区二区三区精品电影| 91成人免费观看网站| 国产欧美日韩精品在线观看| 国产精品免费在线免费| 91国产精品电影| 欧美激情图片区| 亚洲三级av在线| 992tv在线成人免费观看| 亚洲国产中文字幕在线观看| 国产97在线|日韩| 亚洲第一福利网站| 欧美电影免费观看网站| 国产精品一区二区久久| 欧美日韩国内自拍| 97人人爽人人喊人人模波多| 欧美大尺度激情区在线播放| 国产日韩在线播放| 亚洲午夜激情免费视频| 久久久久久久久久久网站| 亚洲一区二区免费| 色婷婷综合成人| 亚洲专区在线视频| 亚洲午夜女主播在线直播| 亚洲欧美在线x视频| 日本欧美在线视频| 久久久国产视频91| 日韩国产中文字幕| 亚洲天堂一区二区三区| 欧美精品久久久久久久| 亚洲xxxx妇黄裸体| 91久久综合亚洲鲁鲁五月天| 日韩免费在线免费观看| 成人精品在线视频| 精品国产老师黑色丝袜高跟鞋| 亚洲xxxx做受欧美| 社区色欧美激情 | 欧美性生交xxxxxdddd| 亚洲欧美激情四射在线日| 91精品国产免费久久久久久| 亚洲春色另类小说| 日韩激情在线视频| 国产午夜精品全部视频在线播放| 亚洲免费视频一区二区| 色哟哟网站入口亚洲精品| 欧美日韩ab片| 一级做a爰片久久毛片美女图片| 91干在线观看| 精品美女久久久久久免费| 成人妇女淫片aaaa视频| 欧美成人亚洲成人| 91夜夜未满十八勿入爽爽影院| 免费不卡欧美自拍视频| 国产精品激情av在线播放| 成人写真福利网| 成人免费自拍视频| 久久99青青精品免费观看| 国产人妖伪娘一区91| 久久久久久久久国产| 久久精品亚洲精品| 国产成人精品国内自产拍免费看| 亚洲国产精品视频在线观看| 成人黄色免费在线观看| 成人午夜激情免费视频| 亚洲第一区中文99精品| 97在线观看免费| 亚洲第一福利网| 亚洲老头老太hd| 欧美成人免费全部| 亚洲国产成人精品久久久国产成人一区| 不卡中文字幕av| 成人在线免费观看视视频| 日韩av在线免播放器| 欧美最猛性xxxx| 亚洲一级黄色片| 亚洲国产小视频在线观看| 欧美日韩爱爱视频| 97国产成人精品视频| 福利视频导航一区| 色悠悠久久88| 久久久久久久久国产| 日韩欧美在线视频日韩欧美在线视频| 亚洲视频第一页| 欧美大片在线看免费观看| 91久久精品日日躁夜夜躁国产| 亚洲国产精久久久久久久| 久久久久久亚洲精品中文字幕| 国产日韩欧美在线| 亲子乱一区二区三区电影| 最近2019年日本中文免费字幕| 色久欧美在线视频观看| 国产极品jizzhd欧美| 日韩精品有码在线观看| 成人免费在线网址| 国产偷亚洲偷欧美偷精品| 最好看的2019的中文字幕视频| 亚洲欧美日韩国产成人| 日本免费久久高清视频| 国产成人啪精品视频免费网| 国产成人精品久久二区二区91| 国产欧美一区二区三区久久人妖| 日韩欧美在线一区| 国产精品久久久久久久7电影| 日韩大片免费观看视频播放| 欧美天天综合色影久久精品| 欧美激情精品久久久久| 日韩黄色在线免费观看| 欧美wwwxxxx| 欧美性猛交xxxx乱大交3| 91亚洲精品久久久久久久久久久久| 国产一区二区三区在线看| 久久久久久久国产精品| 国产精品永久在线| 亚洲一区二区三区香蕉| 亚洲成人av在线播放| 国产精品人成电影在线观看| 欧美日韩激情视频| 正在播放欧美视频| 久久99久久亚洲国产|