976 字
5 分钟
基本操作
Runtime-基本操作
1. 反射 NSString,Class,SEL,Protocol
FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
FOUNDATION_EXPORT NSString *NSStringFromClass(Class aClass);FOUNDATION_EXPORT Class _Nullable NSClassFromString(NSString *aClassName);
FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));FOUNDATION_EXPORT Protocol * _Nullable NSProtocolFromString(NSString *namestr) API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));2. 动态创建一个类
- 创建一个继承
NSObject的类,设定类名并初始化; - 为这个类增加一个实例变量,通过KVC给这个实例变量赋值。
- 为这个类增加一个方法,在这个方法中打印一些值。
- 通过这个类的实例调用新增的方法。
3. 获取一个类的所有方法
class_copyMethodList
实例方法
#import <objc/runtime.h>@implementation NSObject (Runtime)
+ (NSArray *)fetchInstanceMethodList{ unsigned int count = 0; Method *methodList = class_copyMethodList(self, &count);
NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count]; for (unsigned int i = 0; i < count; i++) { Method method = methodList[i]; SEL methodName = method_getName(method); [mutableList addObject:NSStringFromSelector(methodName)]; } free(methodList); return [NSArray arrayWithArray:mutableList];}类方法
+ (NSArray *)fetchClassMethodList{ unsigned int count = 0; Method *methodList = class_copyMethodList(object_getClass(self), &count);
NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count]; for (unsigned int i = 0; i < count; i++) { Method method = methodList[i]; SEL methodName = method_getName(method); [mutableList addObject:NSStringFromSelector(methodName)]; } free(methodList); return [NSArray arrayWithArray:mutableList];}4. 获取一个类的所有成员变量
class_copyIvarList
- (void) getAllVariable { unsigned int count = 0; //获取类的一个包含所有变量的列表,IVar是runtime声明的一个宏,是实例变量的意思. Ivar *allVariables = class_copyIvarList([self class], &count); for(int i = 0;i<count;i++) { //遍历每一个变量,包括名称和类型(此处没有星号"*") Ivar ivar = allVariables[i]; const char *Variablename = ivar_getName(ivar); //获取成员变量名称 const char *VariableType = ivar_getTypeEncoding(ivar); //获取成员变量类型 NSLog(@"(Name: %s) ----- (Type:%s)",Variablename,VariableType); } free(allVariables);}5. 获取一个类的所有属性变量
class_copyPropertyList
- (void) getAllPropertyList { unsigned int count = 0; objc_property_t *allVariables = class_copyPropertyList([self class], &count); for(int i = 0;i<count;i++) { //遍历每一个变量,包括名称和类型(此处没有星号"*") objc_property_t property = allVariables[i]; const char *Variablename = property_getName(property); //获取属性变量名称 const char *VariableType = property_getAttributes(property); //获取属性变量的属性 NSLog(@"(Name: %s) ----- (Type:%s)",Variablename,VariableType); } free(allVariables);} //还有一种写法,注意 object_getClass 中的参数需要是一个对象实例, // 就是说 object_getClass([ChangePayPasswordViewController new]), //和 ChangePayPasswordViewController.Class 意义是一样的 unsigned int a; objc_property_t * result = class_copyPropertyList(object_getClass([ChangePayPasswordViewController new]), &a);6. 获取协议列表
+ (NSArray *)fetchProtocolList{ unsigned int count = 0; __unsafe_unretained Protocol **protocolList = class_copyProtocolList(self, &count);
NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count]; for (unsigned int i = 0; i < count; i++ ) { Protocol *protocol = protocolList[i]; const char *protocolName = protocol_getName(protocol); [mutableList addObject:[NSString stringWithUTF8String:protocolName]]; } return [NSArray arrayWithArray:mutableList];}7. 动态给一个类新增一个方法
/* 动态添加方法: 第一个参数表示Class cls 类型; 第二个参数表示待调用的方法名称; 第三个参数(IMP)myAddingFunction,IMP一个函数指针,这里表示指定具体实现方法myAddingFunction; 第四个参数表方法的参数,0代表没有参数; */class_addMethod([person class], @selector(myAddingFunction), (IMP)myAddingFunction, 0);//调用方法 【如果使用[per NewMethod]调用方法,在ARC下会报“no visible @interface"错误】[person performSelector:@selector(myAddingFunction)];
//具体的实现(方法的内部都默认包含两个参数Class类和SEL方法,被称为隐式参数。)int myAddingFunction(id self, SEL _cmd){ NSLog(@"已新增方法:NewMethod"); return 1;}8. 动态增加实例变量
BOOL isSuccess = class_addIvar(MyClass, "test", sizeof(NSString *), 0, "@");// 三目运算符isSuccess?NSLog(@"添加变量成功"):NSLog(@"添加变量失败");
参数一、类名参数二、属性名称参数三、开辟字节长度参数四、对其方式参数五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型)9. 动态改变对象的某个变量值
- 可以是属性变量(注意加 _ ),也可以是私有的全局变量
Person *person = [[Person alloc]init];person.name = @"asdas";NSLog(@"%@",person.name);[self editObjectIvar:person :@"_name" :@"新属性"];NSLog(@"new :%@",person.name);
- (void)editObjectIvar :(id)object :(NSString *)IvarStr :(NSString *)IvarNewStr
{ unsigned int count = 0; Ivar *allList = class_copyIvarList([object class], &count); for(int i = 0;i<count;i++) { //遍历每一个变量,包括名称和类型(此处没有星号"*") Ivar ivar = allList[i]; const char *Variablename = ivar_getName(ivar); //获取成员变量名称 if ([[NSString stringWithUTF8String:Variablename] isEqualToString:IvarStr]) { object_setIvar(object, ivar, IvarNewStr); //name属性Tom被强制改为Mike。 } } free(allList);}10. 属性关联
略
11. 交换方法
略