Links

01.基本操作

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. 交换方法

参考