runtime實用

不多說

正常開發(fā)中runtime要說吧功能確實強(qiáng)大,但是用的卻是很少,主要是有些用不上,有些吧,可以替代,所以就尷尬了。
但是會用runtime確實能解決很多常規(guī)方法很棘手的偏門問題

1.發(fā)送消息

額,這個方法調(diào)用的本質(zhì),就是讓對象發(fā)送消息

2.交換方法

開發(fā)使用場景:系統(tǒng)自帶的方法功能不夠,給系統(tǒng)自帶的方法擴(kuò)展一些功能,并且保持原有的功能。
1.我們通常的方法,繼承系統(tǒng)的類,重寫方法.(此處略)
2.使用runtime,交換方法.

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 需求:給imageNamed方法提供功能,每次加載圖片就判斷下圖片是否加載成功。
    // 步驟一:寫個分類,定義一個能加載圖片且能打印的方法+ (instancetype)imageWithName:(NSString *)name;
    // 步驟二:交換imageNamed和imageWithName的實現(xiàn),就能調(diào)用imageWithName,間接調(diào)用imageWithName的實現(xiàn)。
    UIImage *image = [UIImage imageNamed:@"speed"];
}
@end

@implementation UIImage (Image)
// 加載分類到內(nèi)存的時候調(diào)用
+ (void)load
{
    // 交換方法
    // 獲取imageWithName方法地址
    Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
    // 獲取imageWithName方法地址
    Method imageName = class_getClassMethod(self, @selector(imageNamed:));
    // 交換方法地址
    method_exchangeImplementations(imageWithName, imageName);
}
// 不能在分類中重寫系統(tǒng)方法imageNamed,因為會把系統(tǒng)的功能給覆蓋掉,而且分類中不能調(diào)用super.
// 既能加載圖片又能打印
+ (instancetype)imageWithName:(NSString *)name
{
   // 這里調(diào)用imageWithName,相當(dāng)于調(diào)用imageName
    UIImage *image = [self imageWithName:name];
    if (image == nil) {
        NSLog(@"沒有圖片");
    }
   return image;
}
@end

3.動態(tài)添加方法

開發(fā)使用場景:如果一個類方法非常多,加載類到內(nèi)存的時候也比較耗費(fèi)資源,需要給每個方法生成映射表,可以使用動態(tài)給某個類,添加方法解決。

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Dog *dog = [[Dog alloc] init];
    // 默認(rèn)Dog,沒有實現(xiàn)eat方法,可以通過performSelector調(diào)用,但是會報錯。
    // 動態(tài)添加方法就不會報錯
    [dog performSelector:@selector(eat)];
}
@end
Dog類繼承自NSObjct,.h文件不作任何操作
@implementation Dog
// 默認(rèn)方法都有兩個隱式參數(shù),
void eat(id self,SEL sel)
{
    NSLog(@"%@ %@",self,NSStringFromSelector(sel));
}
// 當(dāng)一個對象調(diào)用未實現(xiàn)的方法,會調(diào)用這個方法處理,并且會把對應(yīng)的方法列表傳過來.
// 剛好可以用來判斷,未實現(xiàn)的方法是不是我們想要動態(tài)添加的方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(eat)) {
        // 動態(tài)添加eat方法
        // 第一個參數(shù):給哪個類添加方法
        // 第二個參數(shù):添加方法的方法編號
        // 第三個參數(shù):添加方法的函數(shù)實現(xiàn)(函數(shù)地址)
        // 第四個參數(shù):函數(shù)的類型,(返回值+參數(shù)類型) v:void @:對象->self :表示SEL->_cmd
        class_addMethod(self, @selector(eat), eat, "v@:");
    }
    return [super resolveInstanceMethod:sel];
}
@end
打印結(jié)果

4.給分類添加屬性(分類正常情況下是不允許添加屬性)

原理:給一個類聲明屬性,其實本質(zhì)就是給這個類添加關(guān)聯(lián),并不是直接把這個值的內(nèi)存空間添加到類存空間。


@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 給系統(tǒng)NSObject類動態(tài)添加屬性name
    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"Guss";
    NSLog(@"%@",objc.name);
}
@end
//.h
#import <Foundation/Foundation.h>
@interface NSObject (Property)
@property (nonatomic ,copy)NSString *name;
@end

//.m
static const char *key = "name";// 定義關(guān)聯(lián)的key
@implementation NSObject (Property)
- (NSString *)name
{
    // 根據(jù)關(guān)聯(lián)的key,獲取關(guān)聯(lián)的值。
    return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name
{
    // 第一個參數(shù):給哪個對象添加關(guān)聯(lián)
    // 第二個參數(shù):關(guān)聯(lián)的key,通過這個key獲取
    // 第三個參數(shù):關(guān)聯(lián)的value
    // 第四個參數(shù):關(guān)聯(lián)的策略
    objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

5.字典轉(zhuǎn)模型

1.KVC
其實KVC也是可以字典轉(zhuǎn)模型,應(yīng)該沒用第三方前都是這么做的,這樣的字典轉(zhuǎn)模型弊端:必須保證,模型中的屬性和字典中的key一一對應(yīng)。模型中的屬性和字典的key不一一對應(yīng),系統(tǒng)就會調(diào)用setValue:forUndefinedKey:報錯。
解決:重寫對象的setValue:forUndefinedKey:,把系統(tǒng)的方法覆蓋, 就能繼續(xù)使用KVC,字典轉(zhuǎn)模型了。

2.runtime
而用runtime實現(xiàn)字典轉(zhuǎn)模型,其思路是利用運(yùn)行時,遍歷模型中所有成員變量,根據(jù)模型的成員變量,去字典中查找key,取出對應(yīng)的值,給模型的屬性賦值。
3.兩者區(qū)別
兩者的方式本質(zhì)上相反,KVC是通過字典去模型屬性里面去找,而runtime可以做到根據(jù)<成員屬性>去字典里面找,這樣就會更安全

本文就不講這個功能實現(xiàn),因為MJExtersion寫的很好(個人覺得),想具體理解可以看第三方源碼.

總結(jié)

項目中交換方法,動態(tài)添加方法,給分類添加屬性還是能用到的,理解runtime其實能大大增加代碼的性能

沙漠騎士

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

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

  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運(yùn)行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,804評論 7 64
  • Runtime常見應(yīng)用場景 具體應(yīng)用攔截系統(tǒng)自帶的方法調(diào)用(Method Swizzling黑魔法) 實現(xiàn)給分類增...
    Amanda_Lhy閱讀 270評論 0 0
  • 女生啊,變得真快 半開玩笑說句別有意指的話 估計沒仔細(xì)想就拉黑了 也可能就這性格 我愣是思考半天 沒來得及寫作業(yè) ...
    良辰美LiangChen閱讀 171評論 0 0
  • Mysql-基礎(chǔ)語法 導(dǎo)語 本博文主要是簡述選擇數(shù)據(jù)庫和對表內(nèi)容的增、刪、改和查的一些基本語法 USE 語法: U...
    SolaTyolo閱讀 877評論 0 0
  • 文/陌宇軒 (黑龍江) 年輕的時候 我是真喜歡萱草花呀 每到下課 我就會溜到學(xué)校后院的后山采上一捧 我喜形于色 我...
    小哲小詩閱讀 167評論 0 0

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