Contents
  1. 1. Runtime-基本操作
    1. 1.1. 1. 反射 NSString,Class,SEL,Protocol
    2. 1.2. 2. 动态创建一个类
    3. 1.3. 3. 获取一个类的所有方法
      1. 1.3.1. 实例方法
      2. 1.3.2. 类方法
    4. 1.4. 4. 获取一个类的所有成员变量
    5. 1.5. 5. 获取一个类的所有属性变量
    6. 1.6. 6. 获取协议列表
    7. 1.7. 7. 动态给一个类新增一个方法
    8. 1.8. 8. 动态增加实例变量
    9. 1.9. 9. 动态改变对象的某个变量值
    10. 1.10. 10. 属性关联
    11. 1.11. 11. 交换方法
    12. 1.12. 参考

Runtime-基本操作

1. 反射 NSString,Class,SEL,Protocol

1
2
3
4
5
6
7
8
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

实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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];
}

类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+ (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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (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. 获取协议列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+ (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. 动态给一个类新增一个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 动态添加方法:
第一个参数表示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. 动态增加实例变量

1
2
3
4
5
6
7
8
9
BOOL isSuccess = class_addIvar(MyClass, "test", sizeof(NSString *), 0, "@");
// 三目运算符
isSuccess?NSLog(@"添加变量成功"):NSLog(@"添加变量失败");
参数一、类名
参数二、属性名称
参数三、开辟字节长度
参数四、对其方式
参数五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型)

9. 动态改变对象的某个变量值

  • 可以是属性变量(注意加 _ ),也可以是私有的全局变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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. 交换方法

参考

https://www.jianshu.com/p/8225526096c7

Contents
  1. 1. Runtime-基本操作
    1. 1.1. 1. 反射 NSString,Class,SEL,Protocol
    2. 1.2. 2. 动态创建一个类
    3. 1.3. 3. 获取一个类的所有方法
      1. 1.3.1. 实例方法
      2. 1.3.2. 类方法
    4. 1.4. 4. 获取一个类的所有成员变量
    5. 1.5. 5. 获取一个类的所有属性变量
    6. 1.6. 6. 获取协议列表
    7. 1.7. 7. 动态给一个类新增一个方法
    8. 1.8. 8. 动态增加实例变量
    9. 1.9. 9. 动态改变对象的某个变量值
    10. 1.10. 10. 属性关联
    11. 1.11. 11. 交换方法
    12. 1.12. 参考