一. 字典转模型
利用Runtime遍历所有的属性或者成员变量
利用KVC设值
+ (instancetype)yh_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"];
}
[obj setValue:value forKey:name];
}
free(ivars);
return obj;
}
二. 设置和获取成员变量的值
object_setIvar
要求对象类型,所以需要转换类型(__bridge id)(void *)10
// 获取成员变量信息
Ivar ageIvar = class_getInstanceVariable([Person class], "_age");
NSLog(@"%s %s", ivar_getName(ageIvar), ivar_getTypeEncoding(ageIvar));
//设置和获取成员变量的值
Ivar nameIvar = class_getInstanceVariable([Person class], "_name");
Person *person = [[Person alloc] init];
object_setIvar(person, nameIvar, @"123");
object_setIvar(person, ageIvar, (__bridge id)(void *)10);
NSLog(@"%@ %d", person.name, person.age);
// 成员变量的数量
unsigned int count;
Ivar *ivars = class_copyIvarList([Person 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);
三. 查到私有成员变量以后设置私有成员变量
设置UITextField占位文字的颜色
self.textField.placeholder = @"请输入用户名";
[self.textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
四. 替换方法实现
做了方法替换以后,当前类会清空已经缓存的方法列表
Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)run;
- (void)test;
@end
#import "Person.h"
@implementation Person
- (void)run
{
NSLog(@"%s", __func__);
}
- (void)test
{
NSLog(@"%s", __func__);
}
@end
Car类
#import <Foundation/Foundation.h>
@interface Car : NSObject
@end
#import "Car.h"
@implementation Car
- (void)run
{
NSLog(@"%s", __func__);
}
@end
同一个类的方法替换
Person *person = [[Person alloc] init];
Method runMethod = class_getInstanceMethod([Person class], @selector(run));
Method testMethod = class_getInstanceMethod([Person class], @selector(test));
method_exchangeImplementations(runMethod, testMethod);
[person run];
不同类的方法替换
Person *person = [[Person alloc] init];
Method runMethod = class_getInstanceMethod([Person class], @selector(run));
Method testMethod = class_getInstanceMethod([Car class], @selector(run));
method_exchangeImplementations(runMethod, testMethod);
[person run];
方法替换实际是替换的method_t
结构里边的IMP(函数指针)
,所以不同类也可以进行替换。不过一般都是替换同一个类中的方法。
五. 创建类
object_setClass(person, [MJCar class]);
修改对象的类对象,其实就是修改isa指针的指向。
void run(id self, SEL _cmd)
{
NSLog(@"_____ %@ - %@", self, NSStringFromSelector(_cmd));
}
void createClass()
{
// 创建类
Class newClass = objc_allocateClassPair([NSObject class], "MJDog", 0);
class_addIvar(newClass, "_age", 4, 1, @encode(int));
class_addIvar(newClass, "_weight", 4, 1, @encode(int));
class_addMethod(newClass, @selector(run), (IMP)run, "v@:");
// 注册类
objc_registerClassPair(newClass);
Person *person = [[Person alloc] init];
object_setClass(person, newClass);
[person run];
id dog = [[newClass alloc] init];
[dog setValue:@10 forKey:@"_age"];
[dog setValue:@20 forKey:@"_weight"];
[dog run];
NSLog(@"%@ %@", [dog valueForKey:@"_age"], [dog valueForKey:@"_weight"]);
// 在不需要这个类时释放
// objc_disposeClassPair(newClass);
}
六. 类相关用法
-
动态创建一个类(参数:父类,类名,额外的内存空间)
a) Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) -
注册一个类(要在类注册之前添加成员变量)
a) void objc_registerClassPair(Class cls) -
销毁一个类
a) void objc_disposeClassPair(Class cls) -
获取isa指向的Class
a) Class object_getClass(id obj) -
设置isa指向的Class
a) Class object_setClass(id obj, Class cls) -
判断一个OC对象是否为Class
a) BOOL object_isClass(id obj) -
判断一个Class是否为元类
a) BOOL class_isMetaClass(Class cls) -
获取父类
a) Class class_getSuperclass(Class cls)
七. 成员变量
-
获取一个实例变量信息
a) Ivar class_getInstanceVariable(Class cls, const char *name) -
拷贝实例变量列表(最后需要调用free释放)
a) Ivar *class_copyIvarList(Class cls, unsigned int *outCount) -
设置和获取成员变量的值
a) void object_setIvar(id obj, Ivar ivar, id value)
b) id object_getIvar(id obj, Ivar ivar) -
动态添加成员变量(已经注册的类是不能动态添加成员变量的)
a) BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types) -
获取成员变量的相关信息
a) const char *ivar_getName(Ivar v)
a) const char *ivar_getTypeEncoding(Ivar v)
八. 属性
-
获取一个属性
a) objc_property_t class_getProperty(Class cls, const char *name) -
拷贝属性列表(最后需要调用free释放)
a) objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount) -
动态添加属性
a) BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,
unsigned int attributeCount) -
动态替换属性
a) void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,
unsigned int attributeCount) -
获取属性的一些信息
a) const char *property_getName(objc_property_t property)
b) const char *property_getAttributes(objc_property_t property)
九. 方法
-
获得一个实例方法、类方法
a) Method class_getInstanceMethod(Class cls, SEL name)
b) Method class_getClassMethod(Class cls, SEL name) -
方法实现相关操作
a) IMP class_getMethodImplementation(Class cls, SEL name)
b) IMP method_setImplementation(Method m, IMP imp)
c) void method_exchangeImplementations(Method m1, Method m2) -
拷贝方法列表(最后需要调用free释放)
a) Method *class_copyMethodList(Class cls, unsigned int *outCount) -
动态添加方法
a) BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) -
动态替换方法
a) IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) -
获取方法的相关信息(带有copy的需要调用free去释放)
a) SEL method_getName(Method m)
b) IMP method_getImplementation(Method m)
c) const char *method_getTypeEncoding(Method m)
d) unsigned int method_getNumberOfArguments(Method m)
e) char *method_copyReturnType(Method m)
f) char *method_copyArgumentType(Method m, unsigned int index) -
选择器相关
a) const char *sel_getName(SEL sel)
b) SEL sel_registerName(const char *str) -
用block作为方法实现
a) IMP imp_implementationWithBlock(id block)
b) id imp_getBlock(IMP anImp)
c) BOOL imp_removeBlock(IMP anImp)
网友评论