再來(lái)看看費(fèi)腦的Runtime-實(shí)用篇


開(kāi)篇

關(guān)于Runtime,在平時(shí)的開(kāi)發(fā)中,我用得最多的就是方法混淆(Method Swizzling)和動(dòng)態(tài)添加屬性.雖然自己經(jīng)常用,但是很少去深究原理性的東西.今天就重溫一下費(fèi)腦的runtime;

使用場(chǎng)景

runtime的使用場(chǎng)景我總結(jié)一下,大致分為如下幾種,由淺入深.并且附上相關(guān)示例代碼:
  • 1.給分類添加屬性
    目前常用的兩種方式,一種是顯示定義定義屬性關(guān)聯(lián)的key,一種是直接通過(guò)方法名作為屬性關(guān)于的key.
    顯示定義關(guān)聯(lián)的key
Paste_Image.png

** 直接通過(guò)方法名定義關(guān)聯(lián)的key**

隱試關(guān)聯(lián).png
  • 2.方法混淆(Method Swizzling)
    方法混淆在實(shí)際開(kāi)發(fā)中我就用到統(tǒng)計(jì)每個(gè)頁(yè)面進(jìn)入與退出的時(shí)候.其實(shí)完全把方法混洗的代碼抽出來(lái)成為一個(gè)工具.如下:
Swizzlling.png

這種寫(xiě)法稍微要嚴(yán)謹(jǐn)一點(diǎn)
說(shuō)一說(shuō)Method,SEL,IMP之間的關(guān)系,比較重要,我們直接來(lái)看,Method是runtime內(nèi)部定義的方法


Method定義.png

網(wǎng)上找了幾張圖,分析一下具體的實(shí)現(xiàn)過(guò)程

第一步.png
第二步.png
  • 3.動(dòng)態(tài)添加方法(消息轉(zhuǎn)發(fā))
    一般處理的就是當(dāng)類中沒(méi)有定義方法,而調(diào)用了會(huì)包方法找不到的錯(cuò)誤.可以通過(guò)消息轉(zhuǎn)發(fā)搞定這個(gè)異常.具體的消息轉(zhuǎn)發(fā)可以參考這里.來(lái)個(gè)圖吧.
消息轉(zhuǎn)發(fā)流程.png

.在實(shí)際應(yīng)用中一般就走到第一步就OK了.

實(shí)際應(yīng)用.png
  • 4.字典轉(zhuǎn)模型
    字典轉(zhuǎn)模型我一般比較少用,
    這段代碼已經(jīng)用過(guò)好多次,josnModel里面已經(jīng)寫(xiě)爛了.我也只是一名搬運(yùn)工
 + (instancetype)modelWithDict:(NSDictionary *)dict
    {
        // 思路:遍歷模型中所有屬性-》使用運(yùn)行時(shí)
        
        // 0.創(chuàng)建對(duì)應(yīng)的對(duì)象
        id objc = [[self alloc] init];
        
        // 1.利用runtime給對(duì)象中的成員屬性賦值
        
        // class_copyIvarList:獲取類中的所有成員屬性
        // Ivar:成員屬性的意思
        // 第一個(gè)參數(shù):表示獲取哪個(gè)類中的成員屬性
        // 第二個(gè)參數(shù):表示這個(gè)類有多少成員屬性,傳入一個(gè)Int變量地址,會(huì)自動(dòng)給這個(gè)變量賦值
        // 返回值Ivar *:指的是一個(gè)ivar數(shù)組,會(huì)把所有成員屬性放在一個(gè)數(shù)組中,通過(guò)返回的數(shù)組就能全部獲取到。
        /* 類似下面這種寫(xiě)法
         
         Ivar ivar;
         Ivar ivar1;
         Ivar ivar2;
         // 定義一個(gè)ivar的數(shù)組a
         Ivar a[] = {ivar,ivar1,ivar2};
         
         // 用一個(gè)Ivar *指針指向數(shù)組第一個(gè)元素
         Ivar *ivarList = a;
         
         // 根據(jù)指針訪問(wèn)數(shù)組第一個(gè)元素
         ivarList[0];
         
         */
        unsigned int count;
        
        // 獲取類中的所有成員屬性
        Ivar *ivarList = class_copyIvarList(self, &count);
        
        for (int i = 0; i < count; i++) {
            // 根據(jù)角標(biāo),從數(shù)組取出對(duì)應(yīng)的成員屬性
            Ivar ivar = ivarList[i];
            
            // 獲取成員屬性名
            NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            // 處理成員屬性名->字典中的key
            // 從第一個(gè)角標(biāo)開(kāi)始截取
            NSString *key = [name substringFromIndex:1];
            
            // 根據(jù)成員屬性名去字典中查找對(duì)應(yīng)的value
            id value = dict[key];
            
            // 二級(jí)轉(zhuǎn)換:如果字典中還有字典,也需要把對(duì)應(yīng)的字典轉(zhuǎn)換成模型
            // 判斷下value是否是字典
            if ([value isKindOfClass:[NSDictionary class]]) {
                // 字典轉(zhuǎn)模型
                // 獲取模型的類對(duì)象,調(diào)用modelWithDict
                // 模型的類名已知,就是成員屬性的類型
                
                // 獲取成員屬性類型
                NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
                // 生成的是這種@"@\"User\"" 類型 -》 @"User"  在OC字符串中 \" -> ",\是轉(zhuǎn)義的意思,不占用字符
                // 裁剪類型字符串
                NSRange range = [type rangeOfString:@"\""];
                
                type = [type substringFromIndex:range.location + range.length];
                
                range = [type rangeOfString:@"\""];
                
                // 裁剪到哪個(gè)角標(biāo),不包括當(dāng)前角標(biāo)
                type = [type substringToIndex:range.location];
                
                
                // 根據(jù)字符串類名生成類對(duì)象
                Class modelClass = NSClassFromString(type);
                
                
                if (modelClass) { // 有對(duì)應(yīng)的模型才需要轉(zhuǎn)
                    
                    // 把字典轉(zhuǎn)模型
                    value  =  [modelClass modelWithDict:value];
                }
                
                
            }
            
            // 三級(jí)轉(zhuǎn)換:NSArray中也是字典,把數(shù)組中的字典轉(zhuǎn)換成模型.
            // 判斷值是否是數(shù)組
            if ([value isKindOfClass:[NSArray class]]) {
                // 判斷對(duì)應(yīng)類有沒(méi)有實(shí)現(xiàn)字典數(shù)組轉(zhuǎn)模型數(shù)組的協(xié)議
                if ([self respondsToSelector:@selector(arrayContainModelClass)]) {
                    
                    // 轉(zhuǎn)換成id類型,就能調(diào)用任何對(duì)象的方法
                    id idSelf = self;
                    
                    // 獲取數(shù)組中字典對(duì)應(yīng)的模型
                    NSString *type =  [idSelf arrayContainModelClass][key];
                    
                    // 生成模型
                    Class classModel = NSClassFromString(type);
                    NSMutableArray *arrM = [NSMutableArray array];
                    // 遍歷字典數(shù)組,生成模型數(shù)組
                    for (NSDictionary *dict in value) {
                        // 字典轉(zhuǎn)模型
                        id model =  [classModel modelWithDict:dict];
                        [arrM addObject:model];
                    }
                    
                    // 把模型數(shù)組賦值給value
                    value = arrM;
              
                }
            }
            
            
            if (value) { // 有值,才需要給模型的屬性賦值
                // 利用KVC給模型中的屬性賦值
                [objc setValue:value forKey:key];
            }
            
        }
        
        return objc;
    }

### 總結(jié)
這篇簡(jiǎn)單講了一下,runtime在開(kāi)發(fā)中用到的場(chǎng)景.屬于應(yīng)用層面,下篇開(kāi)始講原理
參考鏈接
[快速上手Runtime](http://www.itdecent.cn/p/e071206103a4)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • OC最實(shí)用的runtime總結(jié),面試、工作你看我就足夠了! 前言runtime的資料網(wǎng)上有很多了,部分有些晦澀難懂...
    small_Sun閱讀 972評(píng)論 1 12
  • 對(duì)于從事 iOS 開(kāi)發(fā)人員來(lái)說(shuō),所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢(mèng)夜繁星閱讀 3,812評(píng)論 7 64
  • 一、runtime簡(jiǎn)介 RunTime簡(jiǎn)稱運(yùn)行時(shí)。OC就是運(yùn)行時(shí)機(jī)制,也就是在運(yùn)行時(shí)候的一些機(jī)制,其中最主要的是消...
    Lucky丶晴閱讀 2,233評(píng)論 1 2
  • OC最實(shí)用的runtime總結(jié) 前言 runtime的資料網(wǎng)上有很多了,部分有些晦澀難懂,我通過(guò)自己的學(xué)習(xí)方法總結(jié)...
    姚姚先生閱讀 1,089評(píng)論 0 0
  • 我是一個(gè)活潑開(kāi)朗的陽(yáng)光小男孩,是一個(gè)無(wú)憂無(wú)慮的00后! 我是一個(gè)樂(lè)高小達(dá)人,美國(guó)隊(duì)長(zhǎng),鋼鐵俠,黑...
    李豐名閱讀 339評(píng)論 0 3

友情鏈接更多精彩內(nèi)容