> For the complete documentation index, see [llms.txt](https://ryukiedev.gitbook.io/wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ryukiedev.gitbook.io/wiki/ios/runtime/runtime-ji-ben-cao-zuo.md).

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

略

## 参考

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