成员变量
// 获取成员变量信息
Ivar ageIvar = class_getInstanceVariable([MJPerson class], "_age");
NSLog(@"%s %s", ivar_getName(ageIvar), ivar_getTypeEncoding(ageIvar));
// 设置和获取成员变量的值
Ivar nameIvar = class_getInstanceVariable([MJPerson class], "_name");
MJPerson *person = [[MJPerson 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([MJPerson 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);

object_setIvar(person, ageIvar, (__bridge id)(void *)10);这个方法传的值,必须是OC类型。当成员变量是基本类型时,比如这里是int类型,不能是NSNumber类型@(10),必须用void *并桥接成OC类型。不能用int *桥接class_copyIvarList创建出来的必须释放free(ivars);
类
MJPerson *person = [[MJPerson alloc] init];
[person run];
object_setClass(person, [MJCar class]);
[person run];
NSLog(@"%d %d %d",
object_isClass(person),
object_isClass([MJPerson class]),
object_isClass(object_getClass([MJPerson class]))
);
// NSLog(@"%p %p", object_getClass([MJPerson class]), [MJPerson class]);

// 创建类
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);
MJPerson *person = [[MJPerson 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);
- 添加成员变量和方法,必须在注册类之前。
- 不需要这个类的时要释放
objc_allocateClassPair从名字可以看出(Pair),创建的是两个对象,类对象和元类对象。
字典转模型
#import "NSObject+Json.h"
#import <objc/runtime.h>
@implementation NSObject (Json)
+ (instancetype)mj_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;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
//字典转模型
NSDictionary *json = @{
@"id" : @20,
@"age" : @20,
@"weight" : @60,
@"name" : @"Jack"
// @"no" : @30
};
MJPerson *person = [MJPerson mj_objectWithJson:json];
[MJCar mj_objectWithJson:json];
MJStudent *student = [MJStudent mj_objectWithJson:json];
NSLog(@"123");
}
return 0;
}
属性

方法


int main(int argc, const char * argv[]) {
@autoreleasepool {
MJPerson *person = [[MJPerson alloc] init];
Method runMethod = class_getInstanceMethod([MJPerson class], @selector(run));
Method testMethod = class_getInstanceMethod([MJPerson class], @selector(test));
method_exchangeImplementations(runMethod, testMethod);
[person run];
}
return 0;
}
void myrun()
{
NSLog(@"---myrun");
}
void test()
{
MJPerson *person = [[MJPerson alloc] init];
// class_replaceMethod([MJPerson class], @selector(run), (IMP)myrun, "v");
class_replaceMethod([MJPerson class], @selector(run), imp_implementationWithBlock(^{
NSLog(@"123123");
}), "v");
[person run];
}
具体应用
设置UITextField的placeholder的字体颜色 正常:
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
attrs[NSForegroundColorAttributeName] = [UIColor redColor];
self.textField.attributedPlaceholder = [[NSMutableAttributedString alloc] initWithString:@"请输入用户名" attributes:attrs];
但是也可以,找到这个属性,查看它的类型,然后通过runtime设置。
unsigned int count;
Ivar *ivars = class_copyIvarList([UITextField 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);
Ivar ivar = class_getInstanceVariable([UITextField class],"_placeholderLabel");
NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
NSLog(@"%@",class_getSuperclass(NSClassFromString(@"UITextFieldLabel")));
self.textField.placeholder = @"请输入用户名";
// NSLog(@"%@",class_getSuperclass([UITextFieldLabel class]));//报错,这个类是前向声明。我们必须找到它的父类
//
// //找到UITextFieldLabel的父类
// NSLog(@"%@",class_getSuperclass(NSClassFromString(@"UITextFieldLabel")));
//
//
// [self.textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
UILabel *placeholderLabel = [self.textField valueForKeyPath:@"_placeholderLabel"];
placeholderLabel.textColor = [UIColor redColor];
13.0后不允许用KVC方式,设置其成员变量了。运行崩溃。 用下面的方法:
Ivar ivar = class_getInstanceVariable([UITextField class],"_placeholderLabel");
UILabel *label = object_getIvar(self.textField,ivar);
label.textColor = [UIColor redColor];