Runtime初識

runtime的使用先導(dǎo)入runtime類

#import <objc/runtime.h>

runtime 可以對類操作
舉個(gè)例子
先創(chuàng)建一個(gè)Person類
在.h中聲明方法

/*
1    + resolveInstanceMethod:(SEL)sel      // 為一個(gè)實(shí)例方法動(dòng)態(tài)添加實(shí)現(xiàn)
+ resolveClassMethod:(SEL)sel      //   為一個(gè)類方法動(dòng)態(tài)添加實(shí)現(xiàn)
2     - (id)forwardingTargetForSelector:(SEL)aSelector
//為沒有實(shí)現(xiàn)的方法指定一個(gè)對象
3     - (void)forwardInvocation:(NSInvocation *)anInvocation
//子類重載這個(gè)方法為消息指定其他對象
*/

在.m中使用

#import "Person.h"
#import <objc/runtime.h>

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

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

+ (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age weight:(NSInteger)weight
{
    Person *person = [Person new];
    unsigned int outCount;
    Ivar *ivarList = class_copyIvarList(self, &outCount);
    // obj:要設(shè)置的對象  ivar:要設(shè)置的對象的某一個(gè)屬性value:value
    object_setIvar(person, ivarList[0], name);
    object_setIvar(person, ivarList[1], gender);
    object_setIvar(person, ivarList[2], age);
    object_setIvar(person, ivarList[3], @(weight));
    
    return person;
}

- (void)getPersonMessage
{
    unsigned int outCount;
    Ivar *ivarList = class_copyIvarList([Person class], &outCount);
    for (NSInteger i = 0; i < outCount; i++) {
        NSLog(@"name = %s, value = %@", ivar_getName(ivarList[i]), object_getIvar(self, ivarList[i]));
    }
}

// 編碼
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned int outCount;
    Ivar *ivarList = class_copyIvarList([Person class], &outCount);
    for (NSInteger i = 0; i < outCount; i++) {
        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++) {
            const char *cName = ivar_getName(ivarList[i]);
            NSString *name = [NSString stringWithUTF8String:cName];
            [self setValue:[aDecoder decodeObjectForKey:name] forKey:name];
        }
    }
    return self;
}

/*
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    NSString *selString = NSStringFromSelector(sel);
    if ([selString isEqualToString:@"walkOnTheStreet:"]) {
        // 為一個(gè)沒有實(shí)現(xiàn)的方法動(dòng)態(tài)添加實(shí)現(xiàn)
 
         cls:類
         name:沒有實(shí)現(xiàn)的方法名
         IMP:要添加的實(shí)現(xiàn)
         types:動(dòng)態(tài)添加的實(shí)現(xiàn)的類型編碼
 
        class_addMethod(self, @selector(walkOnTheStreet:), (IMP)walkFunc, "V@:@");
    }
    return [super resolveInstanceMethod:sel];
}
*/
void walkFunc(id self, SEL sel, NSString *str){
    NSLog(@"Person -- %s, %@", __func__, str);
}

// 切換消息轉(zhuǎn)換對象 方式一

/*
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    NSString *selString = NSStringFromSelector(aSelector);
    if ([selString isEqualToString:@"walkOnTheStreet:"]) {
        self.dog = [Dog new];
        return self.dog;
        
    }
    else {
        return [super forwardingTargetForSelector:aSelector];
    }
}
*/

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([Dog instancesRespondToSelector:anInvocation.selector]) {
        self.dog = [Dog new];
        [anInvocation invokeWithTarget:self.dog];
    }
}

// 給方法制定一個(gè)有效的簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
    if (!methodSignature) {
        methodSignature = [Dog instanceMethodSignatureForSelector:aSelector];
    }
    return methodSignature;
}

runtime在類目中的使用

/* 
 void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)     //為某個(gè)類關(guān)聯(lián)某個(gè)對象
 id objc_getAssociatedObject(id object, const void *key)
 //獲取到某個(gè)類的某個(gè)關(guān)聯(lián)對象
 void objc_removeAssociatedObjects(id object) //移除已經(jīng)關(guān)聯(lián)的對象
*/

可以為某個(gè)類關(guān)聯(lián)對象

- (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);
}

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

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

  • 這里就不說runtime有多牛逼了。直接進(jìn)入正題。 首先Objective-C是面向?qū)ο蟮模魏晤惖亩x都是對象。...
    進(jìn)擊的小杰閱讀 961評論 3 7
  • Runtime 運(yùn)行時(shí),是一套底層的 C 語言 API,其為 iOS 內(nèi)部的核心之一,我們平時(shí)編寫的 OC 代碼,...
    剎那_芳華閱讀 352評論 1 0
  • 我們隨便寫一個(gè)小程序,代碼如下: person類頭文件如下, #import@interfacePerson : ...
    program袁閱讀 313評論 0 1
  • Objective-C Runtime Describes the macOS Objective-C runti...
    Jackey_Zhou閱讀 150評論 0 0
  • 蘇州客 S醫(yī)院腫瘤科的大單間,位于護(hù)士站對面,默認(rèn)的重癥室。此時(shí),幾個(gè)家屬默默肅立。 床...
    蘇州客閱讀 335評論 2 2

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