Runtime

1.歸檔與反歸檔

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "Dog.h"
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *gender;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, assign) NSInteger weight;
@property (nonatomic, strong) Dog *dog;
+ (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age weight:(NSInteger)weight;
- (void)getPersonMessage;
- (void)walkonTheStreet:(NSString *)str;
@end
#import "Person.h"
#import <objc/runtime.h>// 導(dǎo)入<objc/runtime.h>
@interface Person ()<NSCoding>
@end

@implementation Person
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned int outCount;
    Ivar *ivarList = class_copyIvarList([Person class], &outCount);
    for (NSInteger i = 0; i < outCount; i++) {  // 采用for循環(huán)遍歷屬性,無需一一歸檔
        const char *cName = ivar_getName(ivarList[i]);
        NSString *name = [NSString stringWithUTF8String:cName];
        [aCoder encodeObject:[self valueForKey:name] forKey:name];
    }   
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        unsigned int outCount;
        Ivar *ivarList = class_copyIvarList([Person class], &outCount);
        for (NSInteger i = 0; i < outCount; i++) { // 采用for循環(huán)遍歷屬性,無需一一反歸檔
            const char *cName = ivar_getName(ivarList[i]);
            NSString *name = [NSString stringWithUTF8String:cName];
            [self setValue:[aDecoder decodeObjectForKey:name] forKey:name];
        }
    }
    return  self;
}

如下方法

Ivar *class_copyIvarList(Class cls, unsigned int *outCount)      //獲取所有成員變量
 const char *ivar_getName(Ivar v)            //獲取某個成員變量的名字
 const char *ivar_getTypeEncoding(Ivar v)   //獲取某個成員變量的類型編碼
 Ivar class_getInstanceVariable(Class cls, const char *name)    //獲取某個類中指定名稱的成員變量
 id object_getIvar(id obj, Ivar ivar)    //獲取某個對象中的某個成員變量的值
 void object_setIvar(id obj, Ivar ivar, id value)    //設(shè)置某個對象的某個成員變量的值
 TypeEncoding:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1  // 編碼形式

打印實例變量

- (NSString *)description
{
    /*
     * class: 要獲取的某個類, outCount: 通過這一個函數(shù)執(zhí)行之后會將成員變量的個數(shù)賦值到此
     */
    unsigned int outCount;
    Ivar *ivarList = class_copyIvarList([Person class], &outCount);
    for (NSInteger i = 0; i < outCount; i ++) {
//        每次獲取一個成員變量
        Ivar ivar = ivarList[i];
//        打印成員變量的名字和類型編碼
        NSLog(@"name = %s, type = %s",ivar_getName(ivar), ivar_getTypeEncoding(ivar));
    }
    return nil;
}

2.消息轉(zhuǎn)發(fā)

OC的消息發(fā)送機制根據(jù)方法名來尋找聲明完成的實例方法的實現(xiàn)方法,當(dāng)類中的方法只聲明而未實現(xiàn)時击敌,系統(tǒng)會在逐級父類中尋找方法的實現(xiàn)期丰,當(dāng)父類中均無方法的實現(xiàn)時, 系統(tǒng)會執(zhí)行以下方法柔逼,故可為未實行的方法進行消息轉(zhuǎn)發(fā)犯犁,添加實現(xiàn)
1    + resolveInstanceMethod:(SEL)sel      // 為一個實例方法動態(tài)添加實現(xiàn)
+ resolveClassMethod:(SEL)sel      //   為一個類方法動態(tài)添加實現(xiàn)
2     - (id)forwardingTargetForSelector:(SEL)aSelector
//為沒有實現(xiàn)的方法指定一個對象
3     - (void)forwardInvocation:(NSInvocation *)anInvocation
//子類重載這個方法為消息指定其他對象

a. 為一個實例方法動態(tài)添加實現(xiàn)

+ (BOOL)resolveInstanceMethod:(SEL)sel 
{
   //    將方法轉(zhuǎn)換為字符串
    NSString *selString = NSStringFromSelector(sel);
    if ([selString isEqualToString:@"walkonTheStreet:"]) {
     //   為一個沒有實現(xiàn)的方法動態(tài)添加實現(xiàn)
        /* cls: 類
         name: 沒有實現(xiàn)的方法
         IMP: 要添加的實現(xiàn)
         types: 動態(tài)添加的實現(xiàn)的類型編碼*/
        class_addMethod(self, @selector(walkonTheStreet:), (IMP)walkFunc, "V@:@");  // void的編碼為 V,  SEL的編碼為 :
    }
    return [super resolveInstanceMethod:sel];
}

void walkFunc(id self,SEL sel, NSString *str){
    NSLog(@"Person---%s------%@", __func__, str);
}

b. 為沒有實現(xiàn)的方法指定一個對象

方式1
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    NSString *selString = NSStringFromSelector(aSelector);
   if ([selString isEqualToString:@"walkonTheStreet:"]) {
       self.dog = [Dog new];
       return self.dog;
   }
    return [super forwardingTargetForSelector:aSelector];
}
方式2
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([Dog instanceMethodSignatureForSelector:anInvocation.selector]) {
        self.dog = [Dog new];
        [anInvocation invokeWithTarget:self.dog];
    }
}

// 給方法制定一個有效的簽名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
    if (!methodSignature) {
        methodSignature = [Dog instanceMethodSignatureForSelector:aSelector];
    }
    return methodSignature;
}

3.給類目添加實例變量

延展可為類添加屬性和方法, 但外界不可訪問; 類目可為類添加方法壁肋,但無法添加實例變量, 采用runtime可為類目添加外界可訪問的實例變量
#import <Foundation/Foundation.h>
@interface NSDictionary (Mydict)
@property (nonatomic,strong) NSString *name;
@end
#import "NSDictionary+Mydict.h"
#import <objc/runtime.h>
@implementation NSDictionary (Mydict)

/*
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)     //為某個類關(guān)聯(lián)某個對象
id objc_getAssociatedObject(id object, const void *key)
//獲取到某個類的某個關(guān)聯(lián)對象
void objc_removeAssociatedObjects(id object) //移除已經(jīng)關(guān)聯(lián)的對象
*/
// 關(guān)聯(lián)后此屬性name在外界可以訪問号胚,并且通過移除對象方法隨時移除
- (void)setName:(NSString *)name
{
//    objc: 要關(guān)聯(lián)的對象  key: 成員變量對應(yīng)的key值
//    @selector(屬性名) value: value
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);  // set方法
}

- (NSString *)name
{
    return objc_getAssociatedObject(self, @selector(name));  //get方法
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市浸遗,隨后出現(xiàn)的幾起案子涕刚,更是在濱河造成了極大的恐慌,老刑警劉巖乙帮,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異极景,居然都是意外死亡察净,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門盼樟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氢卡,“玉大人,你說我怎么就攤上這事晨缴∫肭兀” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長筑悴。 經(jīng)常有香客問我们拙,道長,這世上最難降的妖魔是什么阁吝? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任砚婆,我火速辦了婚禮,結(jié)果婚禮上突勇,老公的妹妹穿的比我還像新娘装盯。我一直安慰自己,他們只是感情好甲馋,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布埂奈。 她就那樣靜靜地躺著,像睡著了一般定躏。 火紅的嫁衣襯著肌膚如雪账磺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天共屈,我揣著相機與錄音绑谣,去河邊找鬼。 笑死拗引,一個胖子當(dāng)著我的面吹牛借宵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矾削,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼壤玫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哼凯?” 一聲冷哼從身側(cè)響起欲间,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎断部,沒想到半個月后猎贴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡蝴光,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年她渴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔑祟。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡趁耗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疆虚,到底是詐尸還是另有隱情苛败,我是刑警寧澤满葛,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站罢屈,受9級特大地震影響嘀韧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜儡遮,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一乳蛾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鄙币,春花似錦肃叶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绩衷,卻和暖如春蹦魔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咳燕。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工勿决, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人招盲。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓低缩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親曹货。 傳聞我的和親對象是個殘疾皇子咆繁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 目錄 Objective-C Runtime到底是什么 Objective-C的元素認(rèn)知 Runtime詳解 應(yīng)用...
    Ryan___閱讀 1,939評論 1 3
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,137評論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,567評論 33 466
  • 1.理解NSObject和元類 1.1 在OC中的對象和類是什么 對象是在objc.h中定義的 類是在runtim...
    HWenj閱讀 925評論 0 3
  • 文中的實驗代碼我放在了這個項目中。 以下內(nèi)容是我通過整理[這篇博客] (http://yulingtianxia....
    茗涙閱讀 924評論 0 6