Runtime系列:常用API(附示例)【06】




3、动态添加成员变量(已经注册的类是不能动态添加成员变量的)



BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types)




4、获取成员变量的相关信息



const char *ivar_getName(Ivar v)

const char *ivar_getTypeEncoding(Ivar v)




5、设置成员变量的值



void object_setIvar(id obj, Ivar ivar, id value)




6、获取成员变量的对象



id object_getIvar(id obj, Ivar ivar)




[](https://gitee.com/vip204888)3、属性

-----------------------------------------------------------------------



1、获取一个属性



objc_property_t class_getProperty(Class cls, const char *name)




2、拷贝属性列表(最后需要调用free释放)



objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)




3、动态添加属性



BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,

              unsigned int attributeCount)



4、动态替换属性



void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,

                  unsigned int attributeCount)



5、获取属性的一些信息



const char *property_getName(objc_property_t property)

const char *property_getAttributes(objc_property_t property)




[](https://gitee.com/vip204888)4、方法

-----------------------------------------------------------------------



1、获得一个实例方法、类方法



Method class_getInstanceMethod(Class cls, SEL name)

Method class_getClassMethod(Class cls, SEL name)




2、方法实现相关操作



IMP class_getMethodImplementation(Class cls, SEL name)

IMP method_setImplementation(Method m, IMP imp)

void method_exchangeImplementations(Method m1, Method m2)




3、拷贝方法列表(最后需要调用free释放)



Method *class_copyMethodList(Class cls, unsigned int *outCount)




4、动态添加方法



BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)




5、动态替换方法



IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)




6、获取方法的相关信息(带有copy的需要调用free去释放)



SEL method_getName(Method m)

IMP method_getImplementation(Method m)

const char *method_getTypeEncoding(Method m)

unsigned int method_getNumberOfArguments(Method m)

char *method_copyReturnType(Method m)

char *method_copyArgumentType(Method m, unsigned int index)




6、选择器相关



const char *sel_getName(SEL sel)

SEL sel_registerName(const char *str)




7、用block作为方法实现



IMP imp_implementationWithBlock(id block)

id imp_getBlock(IMP anImp)

BOOL imp_removeBlock(IMP anImp)




* * *



[](https://gitee.com/vip204888)二、示例

=======================================================================



[](https://gitee.com/vip204888)1、动态创建类、添加成员变量、添加方法

--------------------------------------------------------------------------------------



#import <Foundation/Foundation.h>

void run(id self, SEL _cmd) {

NSLog(@"_____ %@ - %@", self, NSStringFromSelector(_cmd));

}

int main(int argc, const char * argv[]) {

@autoreleasepool {

    // 1、创建类【类型可动态赋值】

    NSString *className = [NSString stringWithFormat:@"ZMDog"];

    Class newClass = objc_allocateClassPair([NSObject class], className, 0);

    // 添加成员变量

    class_addIvar(newClass, "_age", 4, 1, @encode(int));

    class_addIvar(newClass, "_weight", 8, 1, @encode(int));

    // 添加方法

    class_addMethod(newClass, @selector(run), (IMP)run, "v@:");

    // 2、注册类

    objc_registerClassPair(newClass);

    

    {

    		 // 初始化

        id dog = [[newClass alloc] init];

        // 赋值

        [dog setValue:@10 forKey:@"_age"];

        [dog setValue:@20 forKey:@"_weight"];

        // 方法实现

        [dog run];

        // 打印结果

        NSLog(@"%@ %@", [dog valueForKey:@"_age"], [dog valueForKey:@"_weight"]);

    }

    // 3、释放类

    objc_disposeClassPair(newClass);

}

return 0;

}




**注意**:  

1、成员变量一定要在注册类之前实现  

2、方法`objc_disposeClassPair`,如果这个类或子类的实例存在,不要调用。



[](https://gitee.com/vip204888)2、设置isa指向的类

------------------------------------------------------------------------------



**ZMPerson.m:**



#import “ZMPerson.h”

@implementation ZMPerson

  • (void)run {

    NSLog(@“%s”, func);

}

@end




**ZMCar.m:**



#import “ZMCar.h”

@implementation ZMCar

  • (void)run {

    NSLog(@“%s”, func);

}

@end




实现:



int main(int argc, const char * argv[]) {

@autoreleasepool {

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

    [person run];



    object_setClass(person, [ZMCar class]);

    [person run];

}

return 0;

}




打印结果:



[29582:563758] -[ZMPerson run]

[29582:563758] -[ZMCar run]




[](https://gitee.com/vip204888)3、判断类和元类

---------------------------------------------------------------------------



int main(int argc, const char * argv[]) {

@autoreleasepool {

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

    NSLog(@"%d %d %d",

          object_isClass(person),

          object_isClass([ZMPerson class]),

          object_isClass(object_getClass([ZMPerson class]))

          );

}

return 0;

}




打印结果:



[28681:543229] 0 1 1




[](https://gitee.com/vip204888)4、成员变量【获取成员变量信息、成员变量赋值和取值、拷贝成员变量列表】

------------------------------------------------------------------------------------------------------



int main(int argc, const char * argv[]) {

@autoreleasepool {

    // 1、获取成员变量信息

    Ivar ageIvar = class_getInstanceVariable([ZMPerson class], "_age");

    NSLog(@"ageIvar:%s %s", ivar_getName(ageIvar), ivar_getTypeEncoding(ageIvar));



    Ivar nameIvar = class_getInstanceVariable([ZMPerson class], "_name");

    

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

    // 2、设置成员变量的值

    object_setIvar(person, nameIvar, @"123");

    object_setIvar(person, ageIvar, (__bridge id)(void *)10);

    // 3、获取成员变量的值

    NSLog(@"person.name:%@", person.name);

    NSLog(@"person.age:%d",person.age);

    

    NSLog(@"==================");

    // 成员变量的数量

    unsigned int count;

    // 拷贝成员变量数组

    Ivar *ivars = class_copyIvarList([ZMPerson class], &count);

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

        // 取出i位置的成员变量

        Ivar ivar = ivars[i];

        NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));

    }

    // 释放成员变量

    free(ivars);

}

return 0;

}


self.textF.placeholder = @“请填写”;

// 直接修改私有成员变量,在iOS13以后被禁止

// [self.textF setValue:[UIColor redColor] forKeyPath:@“_placeholderLabel.textColor”];

// =================

// 要改成如下方式实现:

// 获取成员变量

Ivar placeholderIvar = class_getInstanceVariable([UITextField class], “_placeholderLabel”);

UILabel *placeholderLabel = object_getIvar(self.textF, placeholderIvar);

//给变量赋值

placeholderLabel.textColor = [UIColor redColor];




[](https://gitee.com/vip204888)5、数模转换

-------------------------------------------------------------------------



**NSObject+Json.h**:



#import <Foundation/Foundation.h>

@interface NSObject (Json)

  • (instancetype)zm_objectWithJson:(NSDictionary *)json;

@end




**NSObject+Json.m**:



#import “NSObject+Json.h”

#import <objc/runtime.h>

@implementation NSObject (Json)

  • (instancetype)zm_objectWithJson:(NSDictionary *)json

{

id obj = [[self alloc] init];



unsigned int count;

// 拷贝示例变量列表

Ivar *ivars = class_copyIvarList(self, &count);

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

    // 取出i位置的成员变量

    Ivar ivar = ivars[i];

    // 获取成员变量名称

    NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)];

    // 移除成员变量首个下划线【_】

    [name deleteCharactersInRange:NSMakeRange(0, 1)];

    

    // 设值

    id value = json[name];

    if ([name isEqualToString:@"ID"]) {

        value = json[@"id"];

    }

    // 通过KVC赋值

    [obj setValue:value forKey:name];

}

// 释放变量

free(ivars);



return obj;

}

@end




**ZMPerson.h**:



#import <Foundation/Foundation.h>

@interface ZMPerson : NSObject

@property (assign, nonatomic) int ID;

@property (assign, nonatomic) int weight;

@property (assign, nonatomic) int age;

@property (copy, nonatomic) NSString *name;

  • (void)run;

@end




**ZMPerson.m**:



#import “ZMPerson.h”

@implementation ZMPerson

  • (void)run {

    NSLog(@“%s”, func);

}

@end




【main.m】实现:



#import <Foundation/Foundation.h>

#import “ZMPerson.h”

#import “NSObject+Json.h”

int main(int argc, const char * argv[]) {

@autoreleasepool {

    // 字典转模型

    NSDictionary *json = @{

                           @"id" : @10,

                           @"age" : @20,

                           @"weight" : @80,

                           @"name" : @"Tony"

                           };

    

    ZMPerson *person = [ZMPerson zm_objectWithJson:json];

}

return 0;

}




[](https://gitee.com/vip204888)6、方法交换

-------------------------------------------------------------------------



**ZMPerson.h:**



#import <Foundation/Foundation.h>

@interface ZMPerson : NSObject

  • (void)run;

  • (void)test;

@end


#import “ZMPerson.h”

@implementation ZMPerson

  • (void)run {

    NSLog(@“%s”, func);

}

  • (void)test {

    NSLog(@“%s”, func);

}

@end




main.m 实现:



#import <Foundation/Foundation.h>

#import <objc/runtime.h>

#import “ZMPerson.h”

int main(int argc, const char * argv[]) {

@autoreleasepool {

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



    Method runMethod = class_getInstanceMethod([ZMPerson class], @selector(run));

    Method testMethod = class_getInstanceMethod([ZMPerson class], @selector(test));

    method_exchangeImplementations(runMethod, testMethod);



    [person run];

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值