Runtime初探

關(guān)于runtime簡單來說就是運(yùn)行時,是系統(tǒng)運(yùn)行的一些機(jī)制,其中最主要的是消息機(jī)制。

example:

OC里面調(diào)用方法:
[objc setName];
在編譯的時候runtime會將上述代碼轉(zhuǎn)換成: objc_msgSend(objc,@seletor(setName));

更詳細(xì)的定義網(wǎng)上有許多,這里就不詳細(xì)介紹,這里主要介紹幾個常用的方法。


一、 數(shù)據(jù)的轉(zhuǎn)換(字典到model)

class_copyPropertyList可以獲取當(dāng)前類的屬性

///通過運(yùn)行時獲取當(dāng)前對象的所有屬性的名稱,以數(shù)組的形式返回
- (NSArray *) allPropertyNames{
    ///存儲所有的屬性名稱
    NSMutableArray *allNames = [[NSMutableArray alloc] init];
    
    ///存儲屬性的個數(shù)
    unsigned int propertyCount = 0;
    
    ///通過運(yùn)行時獲取當(dāng)前類的屬性
    objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount);
    
    //把屬性放到數(shù)組中
    for (int i = 0; i < propertyCount; i ++) {
        ///取出第一個屬性
        objc_property_t property = propertys[i];
        
        const char * propertyName = property_getName(property);
        
        [allNames addObject:[NSString stringWithUTF8String:propertyName]];
    }
    
    ///釋放
    free(propertys);
    
    return allNames;
}

/// 通過字符串來創(chuàng)建該字符串的Setter方法,并返回
- (SEL) creatSetterWithPropertyName: (NSString *) propertyName{
    
    //1.首字母大寫
    propertyName = propertyName.capitalizedString;
    
    //2.拼接上set關(guān)鍵字
    propertyName = [NSString stringWithFormat:@"set%@:", propertyName];
    
    //3.返回set方法
    return NSSelectorFromString(propertyName);
}

/// 把字典賦值給當(dāng)前實(shí)體類的屬性
-(void) assginToPropertyWithDictionary: (NSDictionary *) data{
    
    if (data == nil) {
        return;
    }
    
    ///1.獲取字典的key
    NSArray *dicKey = [data allKeys];
    
    ///2.循環(huán)遍歷字典key, 并且動態(tài)生成實(shí)體類的setter方法,把字典的Value通過setter方法
    ///賦值給實(shí)體類的屬性
    for (int i = 0; i < dicKey.count; i ++) {
        
        ///屬性的存在
        if ([[self allPropertyNames]containsObject:dicKey[i]]) {
            ///2.1 通過getSetterSelWithAttibuteName 方法來獲取實(shí)體類的set方法
            SEL setSel = [self creatSetterWithPropertyName:dicKey[i]];
            
            if ([self respondsToSelector:setSel]) {
                ///2.2 獲取字典中key對應(yīng)的value
                NSString  *value = [NSString stringWithFormat:@"%@", data[dicKey[i]]];
                
                ///2.3 把值通過setter方法賦值給實(shí)體類的屬性
                [self performSelectorOnMainThread:setSel
                                       withObject:value
                                    waitUntilDone:[NSThread isMainThread]];
            }
        }
    }
}
  • 思考
    上面的代碼是在model的成員變量的名稱和字典的key一致的情況下,如何實(shí)現(xiàn)不一致的情況?(一一映射)

二、 歸檔

實(shí)現(xiàn)NSCoding協(xié)議,class_copyIvarList可以獲取當(dāng)前類的成員變量

- (void)encodeWithCoder:(NSCoder *)aCoder {
    Class c = self.class;
    // 截取類和父類的成員變量
    while (c && c != [NSObject class]) {
        unsigned int count = 0;
        
        Ivar *ivars = class_copyIvarList(c, &count);
        
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivars[i];
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            id value = [self valueForKey:key];
            
            [aCoder encodeObject:value forKey:key];
            
        }
        c = [c superclass];
        
        // 釋放內(nèi)存
        free(ivars);
    }
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    
    if (self) {
        Class c = self.class;
        
        // 截取類和父類的成員變量
        while (!c && c != [NSObject class]) {
            
            unsigned int count = 0;
            
            Ivar *ivars = class_copyIvarList([self class], &count);
            
            for (int i=0; i<count; i++) {
                Ivar ivar = ivars[i];
                
                NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
                
                id value = [aDecoder decodeObjectForKey:key];
                
                [self setValue:value forKey:key];
            }
            
            c = [c superclass];
            free(ivars);
        }
        
    }
    return self;
}

三、 關(guān)聯(lián)對象

分類不可以創(chuàng)建屬性,但是可以通過運(yùn)行時來設(shè)置成員變量

static NSString *value = nil;

//設(shè)置關(guān)鍵key
static const char associatedkey;

//保存value值
    value = @"test";
    objc_setAssociatedObject(self, &associatedkey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

//通過 objc_getAssociatedObject 獲取關(guān)聯(lián)對象
    value = objc_getAssociatedObject(self, &associatedkey);

四、 方法替換

增加一個分類,在分類中實(shí)現(xiàn):

+ (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);
        
        // 如果 swizzling 的是類方法, 采用如下的方式:
        // Class class = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(class, originalSelector);
        // Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
        
        //交換實(shí)現(xiàn)
        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

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

應(yīng)用場景:一個項(xiàng)目,替換所有圖片,但是圖片多了一個后綴“_new”,可以替換imageName方法;埋點(diǎn);

五、 方法攔截

方法攔截并轉(zhuǎn)發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運(yùn)行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,812評論 7 64
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • Objective-C 的runtime主要是指盡可能的把編譯和鏈接時要執(zhí)行的邏輯延遲到運(yùn)行時,它是系統(tǒng)在運(yùn)行的時...
    lele8446閱讀 335評論 0 2
  • 本文主要介紹了runtime函數(shù)的大體用法,如需更多的了解可以查看官方文檔,或查看官方相關(guān)源碼 Objective...
    24c41111e47b閱讀 1,841評論 0 3
  • 1.PDF真機(jī)查看,模擬器需要 適配的容器加載,或者模擬器不能查看,比如圖片 視頻 音頻 都有專門的標(biāo)簽 容器可以...
    caozhao閱讀 276評論 0 0

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