OC · 記——Runtime(三) 動(dòng)態(tài)添加方法和屬性

動(dòng)態(tài)添加方法

動(dòng)態(tài)添加方法,就是使用performSelector來添加方法,也就相當(dāng)于懶加載機(jī)制。
如果一個(gè)類的方法很多,加載類到內(nèi)存的時(shí)候耗費(fèi)資源,需要給每個(gè)方法生成映射表,可以使用動(dòng)態(tài)給某個(gè)類,添加方法解決。

首先創(chuàng)建一個(gè)對(duì)象Child,引入runtime頭文件,#import <objc/message.h>。實(shí)現(xiàn)動(dòng)態(tài)添加方法,首先要實(shí)現(xiàn)這個(gè)方法:resolveInstanceMethod。
resolveInstanceMethod調(diào)用:當(dāng)一個(gè)方法沒有實(shí)現(xiàn),但是又調(diào)用了這個(gè),就會(huì)調(diào)用。
resolveInstanceMethod作用:知道哪些方法沒有實(shí)現(xiàn),從而動(dòng)態(tài)添加方法。
class_addMethod(Class cls, SEL name, IMP imp, const char *types)
動(dòng)態(tài)添加方法時(shí)調(diào)用:
1.class:給哪個(gè)類添加方法
2.SEL:方法編號(hào)
3.IMP:方法的實(shí)現(xiàn),函數(shù)入口(指針)
4.types:方法類型,蘋果官方文檔可以查詢。

Paste_Image.png

//定義函數(shù)
/*
 一個(gè)方法默認(rèn)都有兩個(gè)參數(shù):self,_cmd(隱式參數(shù))
 self:方法調(diào)用者
 _cmd:調(diào)用方法的編號(hào)
 */
void home(id self, SEL _cmd, id number)
{
    NSLog(@"調(diào)用了child %@ %@ %@",self,NSStringFromSelector(_cmd),number);
}

//sel:沒有實(shí)現(xiàn)方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{   
    //動(dòng)態(tài)添加child方法
    if (sel == @selector(child:)) {
        
        class_addMethod(self, sel, (IMP)home, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

在控制器中,引入頭文件#import "Child.h"

//動(dòng)態(tài)添加
Child * c = [[Child alloc] init];
[c performSelector:@selector(child:) withObject:@111];

運(yùn)行結(jié)果:

2017-01-18 14:01:34.178 [74402:6542779] 調(diào)用了child <Child: 0x61800000a610> child: 111

動(dòng)態(tài)添加屬性

給一個(gè)類聲明屬性,其實(shí)本質(zhì)就是給這個(gè)類添加關(guān)聯(lián),并不是直接把這個(gè)值的內(nèi)存空間添加到類存空間,也就是對(duì)象本身的屬性可以關(guān)聯(lián)到另外一個(gè)內(nèi)存中。

例如,我給NSObject寫一個(gè)分類,分類中,定義一個(gè)屬性name:@property (nonatomic, strong) NSString * name;

//這樣寫法,對(duì)象在,屬性就會(huì)一直在
    NSObject * oc = [[NSObject alloc] init];
    oc.name = @"123";

現(xiàn)在,我通過runtime動(dòng)態(tài)添加屬性,在需要用到的時(shí)候,再添加。引入runtime頭文件:#import <objc/message.h>
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
動(dòng)態(tài)添加屬性,給某個(gè)對(duì)象產(chǎn)生關(guān)聯(lián),添加屬性:
1.object:給哪個(gè)對(duì)象添加屬性
2.key:屬性名,根據(jù)key去獲取關(guān)聯(lián)的對(duì)象,void * == id
3.value:關(guān)聯(lián)的值
4.policy:策略

//添加屬性,跟對(duì)象有關(guān)
- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (NSString *)name
{
    return objc_getAssociatedObject(self, @"name");
}

在控制器中,代碼如下:

NSObject * objc = [[NSObject alloc] init];
objc.name = @"123";
NSLog(@"%@",objc.name);

運(yùn)行結(jié)果:

2017-01-18 15:20:58.370 [77263:6593950] 123

總結(jié):其實(shí),自xcode 5之后,蘋果就不建議使用底層方法,之前沒接觸runtime的時(shí)候,一直覺得很神秘,通過學(xué)習(xí)了解,明白,使用runtime的方法,可以讓我們更好地了解OC的運(yùn)行機(jī)制,而且在某些開發(fā)場(chǎng)景,使用runtime能夠提高我們的開發(fā)效率。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,762評(píng)論 0 9
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡(jiǎn)介 Runt...
    樂樂的簡(jiǎn)書閱讀 2,154評(píng)論 0 9
  • 本文詳細(xì)整理了 Cocoa 的 Runtime 系統(tǒng)的知識(shí),它使得 Objective-C 如虎添翼,具備了靈活的...
    lylaut閱讀 822評(píng)論 0 4
  • 我想我是雨后的蚯蚓,想出去嗮太陽喘口氣,又怕被碾碎了思緒
    艷兒吖閱讀 190評(píng)論 0 0
  • 所謂安全感,從來不是別人所給予 為什么有什么事,你就會(huì)先想有他在會(huì)怎么怎么樣 有這種想法的,怎么看都像是寄生關(guān)系 ...
    古嵐夜寒閱讀 178評(píng)論 0 0