Runtime 常见用法

OC就是运行时机制。在真正运行的时候发送消息,去决定调用哪个函数。

进入.m 文件 使用终端命令:clang -rewrite-objc xxx.m可以看到编译后的xxx.cpp(C++文件)

1. Runtime 动态添加方法(消息转发机制)

//动态方法解析

//这是NSObject根类提供的类方法,调用时机为当被调用的方法实现部分没有找到,而消息转发机制启动之前的这个中间时刻。

//_cmd 表示方法的编号,打印结果为当前执行的方法名

// type: 方法类型:void用v来表示,id参数用@来表示,SEL用:来表示


+ (BOOL)resolveInstanceMethod:(SEL)sel{

  //Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,const char * _Nullable types

    class_addMethod(self, sel, eat, "v@:");

    return [super resolveInstanceMethod:sel];

}

// objc_msgSend(person,@selector(eat),@"汉堡");消息转发机制

//方法有2个隐藏的函数,id sel;

void eat(id self,SEL _cmd,NSString *obj){

    NSLog(@"chichichi-%@",obj);

}

   //performSelector 可以保证类如果未实现方法的情况下,程序不崩溃。

Person *person = [[Person alloc]init];

// objc_msgSend(person,@selector(eat),@"汉堡");消息转发机制

[person performSelector:@selector(eat:) withObject:@"汉堡"];


2 使用Runtime 归档(归档类+父类)

#import <Foundation/Foundation.h>

#import "Pepoles.h"

@interface Person : Pepoles<NSCoding>

@property(nonatomic,copy)NSString *name;

@property(nonatomic,assign)NSNumber *age;

//@property(nonatomic,assign)int age;

@end

#import "Person.h"

#import <objc/runtime.h>


//使用runtime来存数据


@implementation Person


//方法一:使用 object_setIvar /object_getIvar 这个方法多用在类的属性个数 知道的情况。

注意:类的属性申明时不能出现C的基础类型,比如Person的age 不能申明为int age;

object_getIvar 返回什么取决于 ivar 是什么,并不是你看到的那种返回的是id 类型。

ivar 结构体指针,object_getIvar 的返回id 任意类型的对象指针。如果是int 的会造成指向一个int 类型的地址去操作对象的事情,然后就炸了

方法二:KVC方法

// 取

- (instancetype)initWithCoder:(NSCoder *)aDecoder{

    if (self == [super init]) {

        Person *obj = [[Person alloc]init];

        Class cls = obj.class;

        while ([NSStringFromClass(cls) isEqualToString:@"NSObject"]!=YES) {

            

        unsigned int count = 0;

//获取类中所有的实例变量。记住:不包含父类的

        Ivar *list = class_copyIvarList(cls, &count);

        for (int i = 0; i<count; i++) {

            Ivar ivar = list[i];

        

            const char *name =  ivar_getName(ivar);

          NSString *key = [NSString stringWithUTF8String:name];

            //设置实例对象中Ivar的值

            //void object_setIvar(id obj, Ivar i

            id value =   [aDecoder decodeObjectForKey:key]; 


          // [self setValue:value forKey:key]; 方法二KVC 存值

           object_setIvar(self, ivar, value);方法一

        } 

        //获取父类

            cls = class_getSuperclass(cls);

        free(list);

    }

//        self.age = [aDecoder decodeIntForKey:@"age"];

//        self.name = [aDecoder decodeObjectForKey:@"name"];

        

    }

    return self;

}


//存

- (void)encodeWithCoder:(NSCoder *)deCoder{

    Person *obj = [[Person alloc]init];

    Class cls = obj.class;

    while ([NSStringFromClass(cls) isEqualToString:@"NSObject"]!=YES) {

    unsigned int count = 0;

    

    Ivar *list = class_copyIvarList(cls, &count);

    for (int i = 0; i<count; i++) {

       Ivar ivar =  list[I];

   //获得成员变量的名字

       const char * name =  ivar_getName(ivar);

        NSString *key = [NSString stringWithUTF8String:name];

       //id value = [self valueForKey:key];KVC 取值

        id value = object_getIvar(self, ivar);

        [deCoder encodeObject:value forKey:key];

    }

          cls = class_getSuperclass(cls);

//结构体指针数组 要手动释放。

          free(list);

    }

//    [deCoder encodeObject:self.name forKey:@"name"];

//    [deCoder encodeInt:self.age  forKey:@"age"];

    

}

@end

3. Runtime 动态增加分类属性

- (void)setAge:(int)age{

    objc_setAssociatedObject(self, @"a", @(age), OBJC_ASSOCIATION_ASSIGN);

}

- (int)age{


    return [objc_getAssociatedObject(self, @"a") intValue];

}

4.Runtime 方法交换,传说中的黑魔法Method Swizzling(写在分类中)

SEL 方法的ID,IMP 函数指针,指向了方法的实现,可以吧SEL 当作key IMP value

     SEL  originalSelector = @selector(viewWillAppear:);

     SEL  swizzledSelector = @selector(xxx_viewWillAppear:);

//class_getInstanceMethod 获取实例方法

     Method originalM = class_getInstanceMethod(class, originalSelector);

     Method swizzleM = class_getInstanceMethod(class, swizzledSelector);

//方法交换

    method_exchangeImplementations(originalMethod, swizzledMethod);




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值