- (void)runtime {
/// 获取类名
const char *className = class_getName([NSObject class]);
/// 获取父类
Class supperClass = class_getSuperclass([self class]);
/// 判断某个类是否是metaclass
BOOL isMeta =class_isMetaClass([NSObject class]);
/// 获取生成对象需要的大小
size_t size = class_getInstanceSize([self class]);
/// 获取实例变量(在类中声明变量的时候会自动生成实例变量,加下划线即可获取)
Ivar ivar = class_getInstanceVariable([self class], "_allDataArr");
/// 这个方法表示的是类变量,但是公开的api是没有这个的,或许是内部使用的方法,目前用不到
Ivar ivarClass = class_getClassVariable([self class], "");
/// 该函数只能在动态添加类中使用有效,且只能在objc_allocatelasspair()之后和objc_registerClassPair()之前调用,
/// 动态生成类
Class Person = objc_allocateClassPair([NSObject class], "Person", 0);
BOOL addOvar = class_addIvar([Person class], "_myData", sizeof(NSString *), log2(sizeof(NSString *)), "@");
BOOL addOvar1 = class_addIvar([Person class], "_myData1", sizeof(NSString *), log2(sizeof(NSString *)), "@");
objc_registerClassPair(Person);
/// 给成员变量赋值
id person = Person.new;
Ivar personIvar = class_getInstanceVariable([Person class], "_myData");
object_setIvar(person, personIvar, @"test");
NSLog(@"ivar值:%@",object_getIvar(person, personIvar));
/// 获取实例变量列表
unsigned int ivarCount;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
/// 获取类中使用strong修饰的实例对象列表
/// 这个方法获取的内容值的解读,参考 https://www.51cto.com/article/493255.html
const uint8_t *strongs = class_getIvarLayout([self class]);
int i = 0;
uint8_t value_s = strongs[i];
while (value_s != 0x0) {
printf("\\x%02x\n", value_s);
value_s = strongs[++i];
}
/// 获取类中使用weak修饰的实例对象列表(strong和weak都未获得的是基本数据类型)
const uint8_t *weaks = class_getWeakIvarLayout([DDCollectionCycleController class]);
/// 添加实例对象修饰符(strong,weak,retain......)该方法未理清
// class_setIvarLayout([Person class], <#const uint8_t * _Nullable layout#>)
/// 获取属性
objc_property_t property_t = class_getProperty([self class], "property");
/// 获取属性列表
unsigned int property_count;
objc_property_t *property_list = class_copyPropertyList([self class], &property_count);
/// 动态添加方法
SEL sel = NSSelectorFromString(@"testMethod");
Method method_t = class_getInstanceMethod([self class], sel);
BOOL isMethod = class_addMethod([self class], sel, method_getImplementation(method_t), method_getTypeEncoding(method_t));
/// 获取指定对象方法
Method methodInstance = class_getInstanceMethod([self class], @selector(testMethod));
///获取类方法
Method methodClass = class_getClassMethod([self class], @selector(classMethod));
/// 获取方法列表
unsigned int methodCount;
Method methodInstance_list = class_copyMethodList([self class], &methodCount);
/// 方法替换
class_replaceMethod([self class], @selector(swizzMethod), class_getMethodImplementation([self class], @selector(originMethod)), method_getTypeEncoding(class_getInstanceMethod([self class], @selector(originMethod))));
/// 获取方法的imp
IMP imp = class_getMethodImplementation([self class], @selector(originMethod));
/// 查找类中是否包含某个实例方法,但是官方不建议使用这个方法建议使用 respondsToSelector: 或者 instancesRespondToSelector:
BOOL isContainMethod = class_respondsToSelector([self class], @selector(originMethod));
/// 添加协议Protocol到类中
Protocol *protocol = @protocol(UITextFieldDelegate);
BOOL isProtocol = class_addProtocol([self class], protocol);
/// 添加属性
Class currentClass = [self class];
NSString * propertyName = @"myProperty";
// type(举例NSString类型)
objc_property_attribute_t type = { "T", "@\"NSString\""};
// C = copy
objc_property_attribute_t ownership0 = { "C", "" };
// N = nonatomic
objc_property_attribute_t ownership = { "N", "" };
// instance variable name
objc_property_attribute_t backingivar = { "V", [[NSString stringWithFormat:@"_%@", propertyName] UTF8String] };
// 对比系统生成的顺序,例如我们静态添加的grade属性
objc_property_attribute_t attrs[] = { type, ownership0, ownership, backingivar};
BOOL isProperty = class_addProperty(self.class, "myProperty", attrs, 4);
if (!isProperty) {
// 添加属性失败,替换属性
class_replaceProperty(currentClass, "myProperty", attrs, 4);
}
// 添加get和set方法不好使,一直闪退,所以通过关联对象的方式添加
// BOOL add = class_addMethod(currentClass, NSSelectorFromString(propertyName), (IMP)getter, "@@:");
// BOOL addM = class_addMethod(currentClass, NSSelectorFromString(@"setMyProperty:"), (IMP)setter, "v@:@");
objc_setAssociatedObject(self, "myProperty", @"12233", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
NSString *valueData = objc_getAssociatedObject(self, "myProperty");
/// 检测某个类是否遵循某个协议,官方不建议使用这个方法,使用NSObject的conformsToProtocol:
BOOL isConformsProtocol = class_conformsToProtocol([self class], @protocol(UITableViewDelegate));
/// 设置类的版本号,不明白这个用来干啥的
class_setVersion(self.class, 2);
/// 获取类的版本号
int n = class_getVersion(self.class);
///objc_getFutureClass , objc_setFutureClass这两个方法官方原话是Do not call this function yourself
/// 动态添加类
Class PlusClass = objc_allocateClassPair([NSObject class], "PlusClass", 0);
objc_registerClassPair(PlusClass);
/// 创建对象
id plus = class_createInstance(PlusClass.class, sizeof(unsigned));
id strInstance = class_createInstance(NSString.class, sizeof(unsigned));
strInstance = @"string";
/// 释放类 !!!不要调用这个方法,如果有子类继承或者对象使用这个类
/// objc_disposeClassPair(PlusClass);
/// objc_destructInstance,objc_constructInstance arc下无法使用
/// 获取实例关联的信息,一个list
void * indexedIvars = object_getIndexedIvars(plus);
/// 给实例变量赋值
object_setIvar(person, personIvar, @"上面已经赋值了,我是第二次赋值");
/// 获取实例变量Ivar存储的值,前提是保证Ivar存在
id ivar_item = object_getIvar(person, personIvar);
/// 根据对象获取类名
char *name = object_getClassName(person);
/// 获取类对象
Class class = object_getClass(person);
/// 讲一个对象设置其他类类型,返回之前的class
Class replaceClass = object_setClass(plus, NSString.class);
plus = @"11111";
/// 获取已注册的类的列表,以下代码为官方提供使用案例
int numClasses;
Class * classes = NULL;
classes = NULL;
numClasses = objc_getClassList(NULL, 0);
if(numClasses > 0){
/// 开内存
classes = (Class *)realloc(classes, sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);
for (int i = 0; i < numClasses; i++) {
const char *className = class_getName(classes[i]);
// NSLog(@"%s", className);
}
}
free(classes);
/// 获取已注册的类比上面的省事
unsigned int outCount;
Class *copyClasses = objc_copyClassList(&outCount);
for (int i = 0; i < outCount; i++) {
const char *className = class_getName(classes[i]);
// NSLog(@"%s", className);
}
/// 通过类名获取类, objc_getClass,objc_lookUpClass,objc_getRequiredClass,作用一样,但是注意📢objc_getRequiredClass这个更危险,找不到会杀死当前进程
Class lookUpClass = objc_lookUpClass("DDCollectionCycleController");
Class tmp = objc_getRequiredClass("DDCollectionCycleController");
/// 获取元类对象,通过终端发现元类是NSObject
id meta = objc_getMetaClass("UIViewController");
/// po meta
/// UIViewController
/// e object_getClass(meta)
/// (Class _Nullable) $1 = 0x0000000229060db0
/// (lldb) po $1
/// NSObject
/// 获取实例对象的name
char * ivar_name = ivar_getName(personIvar);
/// 获取实例对象的编码方式
char *ivar_type = ivar_getTypeEncoding(personIvar);
/// 创建关联对象
objc_setAssociatedObject(person, @"user_name", @"DDS", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
/// 获取关联对象的值
id user_name = objc_getAssociatedObject(person, @"user_name");
/// 删除obj全部关联对象
/// objc_removeAssociatedObjects(person);
/// 消息发送objc_msgSend,这种写法需要引入<objc/message.h>,他还有好几个兄弟,不一一介绍
((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)self, sel_registerName("test1:"),@"");
/// 方法调用
/// method_invoke
/// 择日继续更新
NSLog(@"%s",className);
}
+ (void)classMethod {
}
- (void)originMethod {
}
- (void)swizzMethod {
}
- (void)test1:(NSString *)t {
}
id getter(id self, SEL _cmd) {
NSString *key = [NSString stringWithFormat:@"_%@",NSStringFromSelector(_cmd)];
Ivar ivar = class_getInstanceVariable([self class], key.UTF8String);
id value = object_getIvar(self, ivar);
return value;
}
void setter(id self, SEL _cmd, id newValue) {
//移除set
NSString *key = [NSStringFromSelector(_cmd) stringByReplacingCharactersInRange:NSMakeRange(0, 3) withString:@""];
//首字母小写(不支持开发者故意把属性名称首字母大写的可能)
NSString *head = [key substringWithRange:NSMakeRange(0, 1)];
head = [head lowercaseString];
key = [key stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:head];
//移除后缀 ":"
key = [key stringByReplacingCharactersInRange:NSMakeRange(key.length - 1, 1) withString:@""];
Ivar ivar = class_getInstanceVariable([self class], [NSString stringWithFormat:@"_%@",key].UTF8String);
object_setIvar(self, ivar, newValue);
}
网友评论