Runtime 在項目中的用處.

1. 全局替換系統的方法為自己的方法

使用UIImage imageNamed 加載圖片時,由于需要手動輸入名稱,這個很容易導致加載的圖片對象為空, 這個問題很容易忽視. 這時如果替換掉系統的方法, 并判斷是否為空,并打印出來 這就很直觀.

@implementation UIImage (image)


//分類被加入運行時的時候就調用,在main方法之前.
+(void)load{
    
    // 1.獲取系統方法
    Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
    
    // 2.自己實現的方法
    Method ln_imageNamedMethod = class_getClassMethod(self, @selector(ln_imageNamed:));
    
    
    //3.交換方法
    method_exchangeImplementations(imageNamedMethod, ln_imageNamedMethod);
}

+(UIImage *)ln_imageNamed:(NSString *)name{
    
    //這里是關鍵,因為ln_imageNamed已經 和 imageNamed交換,這里實際調用的是imageNamed,并不會導致循環調用.
    UIImage *image = [UIImage ln_imageNamed:name];
    if (image) {
        NSLog(@"runtime添加額外功能--加載成功");
    }else{
        NSLog(@"runtime添加額外的功能--加載失敗");
    }
    
    
    return image;
}


@end

//使用
[UIImage imageNamed:@"imageName"];

2. 給系統的類增加屬性.

系統的類不能滿足自己的需求,需要增加額外的屬性.其實本質就是給這個類添加關聯,并不是直接把這個值的內存空間添加到類存空間。


@interface NSObject (Property)


@property NSString *name;


@end


@implementation NSObject (Property)

- (void)setName:(NSString *)name{
    
    //將屬性的值和傳遞進的name關聯
    objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
}

-(NSString *)name{
    
    //獲取關聯屬性的值
    return objc_getAssociatedObject(self, @"name");
}

@end

3. 自己實現字典轉屬性

@interface NSObject (DictToModel)
+(instancetype)modelWithDict:(NSDictionary *)dict;
@end

@implementation NSObject (DictToModel)


+(instancetype)modelWithDict:(NSDictionary *)dict{
    
    //1.創建對象
    id objc = [[self alloc]init];
    
    // 2.利用runtime給對象中的屬性賦值
    /**
     class_copyIvarList: 獲取類中的所有成員變量
     Ivar:成員變量
     第一個參數:表示獲取哪個類中的成員變量
     第二個參數:表示這個類有多少成員變量,傳入一個Int變量地址,會自動給這個變量賦值
     返回值Ivar *:指的是一個ivar數組,會把所有成員屬性放在一個數組中,通過返回的數組就能全部獲取到。
     count: 成員變量個數
     */
    unsigned int count = 0;
    
    //3.獲取類中所有的成員變量
    Ivar *ivarList  =  class_copyIvarList(self, &count);
    
    //遍歷數組所有成員變量
    for (int i = 0; i < count; i++) {
        //從數組中取出對應的成員
        Ivar ivar = ivarList[i];
        //獲取成員變量的名字
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        //處理成員變量 -> 字典中的key(去掉_ )
        NSString *key = [ivarName substringFromIndex:1];
        NSLog(@"ivarName:%@",key);
        //根據成員屬性名去字典查找對應的value
        id value = dict[ivarName];
        
        //找到value
        if (value) {
            //模型中的屬性賦值
            [objc setValue:value forKey:key];
        }
    }
    
    
    
    
    return objc;
}


@end

4.動態添加方法

如果一個類方法非常多,加載類到內存的時候比較耗費資源,需要給每個方法生產映射表,可以動態給某個類,添加方法來解決.

@implementation PersonModel


// 沒有返回值,1個參數
// void,(id,SEL)
void aaa(id self, SEL _cmd, NSNumber *meter) {
    NSLog(@"跑了%@米", meter);
}

// 任何方法默認都有兩個隱式參數,self,_cmd(當前方法的方法編號)
// 什么時候調用:只要一個對象調用了一個未實現的方法就會調用這個方法,進行處理
// 作用:動態添加方法,處理未實現
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    // [NSStringFromSelector(sel) isEqualToString:@"run"];
    if (sel == NSSelectorFromString(@"run:")) {
        // 動態添加run方法
        // class: 給哪個類添加方法
        // SEL: 添加哪個方法,即添加方法的方法編號
        // IMP: 方法實現 => 函數 => 函數入口 => 函數名(添加方法的函數實現(函數地址))
        // type: 方法類型,(返回值+參數類型) v:void  @:對象->self  :表示SEL->_cmd
        class_addMethod(self, sel, (IMP)aaa, "v@:@");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}


@end

//使用
    // 默認PersonModel,沒有實現run:方法,可以通過performSelector調用,但是會報錯。
    // 動態添加方法就不會報錯
    PersonModel *person = [PersonModel new];
    [person performSelector:@selector(run:) withObject:@10];

//輸出
跑了10米


參考
http://www.lxweimin.com/p/19f280afcb24

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 對于從事 iOS 開發人員來說,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,732評論 7 64
  • 把網上的一些結合自己面試時遇到的面試題總結了一下,以后有新的還會再加進來。 1. OC 的理解與特性 OC 作為一...
    AlaricMurray閱讀 2,592評論 0 20
  • 沒關系、我就當你已經死了!
    請叫我小馬同志閱讀 174評論 0 0
  • 越長大周圍的空氣越稀薄,人們的距離喜歡保持在安全的范圍內,保證自己的生存,我不愿與你說,與你說你也聽不清,我們...
    愛打哈欠的貓貓大人閱讀 220評論 0 1