RunTime是什么本缠?
眾所周知OC是一門高級編程語言,也是一門動態(tài)語言。有動態(tài)語言那也就有靜態(tài)語言,靜態(tài)語言---編譯階段就要決定調(diào)用哪個函數(shù)宴胧,如果函數(shù)未實現(xiàn)就會編譯報錯。如C語言表锻。動態(tài)語言---編譯階段并不能決定真正調(diào)用哪個函數(shù)恕齐,只要函數(shù)聲明過即使沒有實現(xiàn)也不會報錯。如OC語言瞬逊。
高級編程語言想要成為可執(zhí)行文件需要先編譯為匯編語言再匯編為機器語言显歧,機器語言也是計算機能夠識別的唯一語言,但是OC并不能直接編譯為匯編語言确镊,而是要先轉(zhuǎn)寫為純C語言再進行編譯和匯編的操作士骤,從OC到C語言的過渡就是由runtime來實現(xiàn)的。然而我們使用OC進行面向?qū)ο箝_發(fā)蕾域,而C語言更多的是面向過程開發(fā)拷肌,這就需要將面向?qū)ο蟮念愞D(zhuǎn)變?yōu)槊嫦蜻^程的結(jié)構(gòu)體。
RunTime的使用場景束铭?
場景1-交換方法
在真正做項目的時候廓块,有時候會接受不同的項目,但是對于你接受的項目契沫,有自己新搭建的項目带猴,也有經(jīng)過很多人手的項目,參差不齊懈万,對于有些需求拴清,修改涉及到以前的代碼,如果一點點的修改会通,費時費力而且見效很慢口予,這時候就可以使用Runtime的交換方法來統(tǒng)一處理,我在做項目的時候就遇到過這種需求涕侈,需要將項目中所有有負值的地方全部處理成紅色沪停,我采用的就是和系統(tǒng)的setText:方法交換,僅僅就換了幾分鐘就將這個需求搞定裳涛。
#import <UIKit/UIKit.h>?
@interface UILabel (TextStyle)?
@end
#import "UILabel+TextStyle.h"
#import?<objc/runtime.h>
@implementation UILabel (TextStyle) ?
+ (void) load { ? ?
????Method method1 = class_getInstanceMethod([UILabel class], @selector(setText:)); ? ? ????Method method2 = class_getInstanceMethod([UILabel class],@selector(setTextString:)); ? ?
????method_exchangeImplementations(method1, method2);
} ?
- (void)setTextString:(NSString *)textString { ? ?
????if (![textString isEqualToString:@"-"] && [textString hasPrefix:@"-"]) {
????//對于負值進行標紅處理 ? ? ? ?
????????self.textColor = [UIColor redColor]; ? ?
????} ? ?
????[self setTextString:textString];
}
@end
這里我就將setText:和setTextString:交換木张,之前使用label給text賦值的語句,其實全部調(diào)用的
是setTextString:方法給label賦值端三,這樣就完成了對項目的修改舷礼。
場景2-動態(tài)擴展屬性
OC中類可以通過Category來直接擴展方法,但是卻不能直接通過添加屬性來擴展屬性(以我項目中用到的一個為例)郊闯。
這里需要使用到objc_setAssociatedObject()和objc_getAssociatedObject()方法妻献;
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
objc_setAssociatedObject()的主要作用是:讓一個對象和另一個對象關(guān)聯(lián)起來蛛株,即一個對象保持對另一個對象的引用,并可以獲取這個對象育拨。關(guān)鍵字是一個void類型的指針谨履。每個關(guān)鍵字必須是唯一的,通常都是會采用靜態(tài)變量來作為關(guān)鍵字至朗。
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key) OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
#import <UIKit/UIKit.h>
?@interface UIView (SPUtils)?
????@property(nonatomic) NSString * testString;?
@end
#import "UIView+SPUtils.h"
#import <objc/runtime.h>
@implementation UIView (SPUtils)
-(void)setTestString:(NSString?*)testString{
????objc_setAssociatedObject(self, @selector(testString), testString,OBJC_ASSOCIATION_RETAIN);
}
-(NSString?*)testString{????
????return?objc_getAssociatedObject(self,?_cmd);
}
?@end
這樣在使用在其他中創(chuàng)建UIView對象屉符,可以直接使用testString屬性了!
場景3-實現(xiàn)字典和模型的自動轉(zhuǎn)換(MJExtension)
使用RunTime提供的函數(shù)遍歷model自身的所有屬性锹引,如果屬性在json中有對應的值矗钟,則將其復制。核心方法:在NSObject的分類中添加方法嫌变。
#import <Foundation/Foundation.h>
?@interface?NSObject?(MutableCopy)?
- (instancetype) initWithDict:(NSDictionary *)dict;?
@end
#import "NSObject+MutableCopy.h"
#import <objc/runtime.h>?
@implementation?NSObject?(MutableCopy)
- (instancetype) initWithDict:(NSDictionary *)dict{
????if (self = [self init]) {
????????//(1)獲取類的屬性及屬性對應的類型
????????NSMutableArray * keys = [NSMutableArray array];????????
????????NSMutableArray?*?attributes?=?[NSMutableArray?array];
????????unsigned int outCount;
????????objc_property_t * properties = class_copyPropertyList([self class], &outCount);
? ? ? ? for (int i = 0; i < outCount; i ++) {
????????????objc_property_t property = properties[i];
????????????//通過property_getName函數(shù)獲得屬性的名字
????????????NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
????????????[keys addObject:propertyName];
????????????//通過property_getAttributes函數(shù)可以獲得屬性的名字和@encode編碼
????????????NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];????
????????????[attributes addObject:propertyAttribute];
????????} //立即釋放properties指向的內(nèi)存
????????free(properties);
????????//(2)根據(jù)類型給屬性賦值
????????for (NSString * key in keys) {
????????????if ([dict valueForKey:key] == nil) continue;
????????????[self setValue:[dict valueForKey:key] forKey:key];
????????}
????}
return self;
}?
@end
目前就RunTime就研究這么多吨艇,有興趣的點個關(guān)注,關(guān)注不迷路額L谏丁6小!喜歡的朋友可以關(guān)注個人微信公眾號:IT科學技術(shù)