runtime 基础篇(一)

#import "DisplayAttribute.h"
#import 

@implementation DisplayAttribute
/**
 *  必备常识:
 *  Ivar : 成员变量    如果要是动态创建/修改/查看属性,可以使用Ivar
 *  Method : 成员方法  如果要是动态创建/修改/查看方法,可以使用Method
 *  下面的例子教大家一些runtime简单的 查看类中属性和方法以及动态添加属性和方法和修改属性.
 */

/**
 *  通过类的名字来获取类里面包含的所有属性
 *
 *  @param className 类名(egs:UIView)
 */
- (void)getIvarsNameListWithClassName:(NSString *)className
{
    //通过类的名字获取到类(egs:通过"学生"这个类的名字找到"学生"这个类)
    Class ClassName = NSClassFromString(className);
    
    //定义一个变量来存放遍历出来类里面属性的个数
    unsigned int outConut = 0;
    //查取类里面所有的属性
    Ivar * vars = class_copyIvarList([ClassName class], &outConut);
    //打印类里面有多少个属性
    NSLog(@"%d",outConut);
    
    //遍历类里面所有的属性 和 属性类型
    for (int i = 0; i < outConut; i ++) {
        //获取类里面属性的名字(将IVar变量转化为字符串)
        const char * ivarName = ivar_getName(vars[i]);
        //获取类里面属性的类型(获取IVar的类型)
        const char * ivarType = ivar_getTypeEncoding(vars[i]);
        //打印属性的名字和类型
        printf("属性名字:%s 属性类型:%s\n",ivarName,ivarType);
        
        /**
         *  如果你想对这个类动态赋值修改的话,有两种
         1:可以用KVC模式来进行赋值修改.不管它有没有在.h中声明(只要类中有这个属性),都可以赋值
         *  例如:类中有一个属性为:"name",你这个时候就可以直接赋值了.
         *  [p1 setValue:@"东方_未明" forKey:@"name"];
         2:Ivar name = vars[1];//找到对应的下表
         *  object_setIvar(p1, name, @"童星");
         *  可以打印查看有没有修改成功
         *  NSLog(@"%@",[p1 valueForKey:@"name"]);
         */
    }
    /**
     *  动态为类添加属性
     */
    //通过类名获取到的类,创建一个对象
    NSObject *p1 = [[[ClassName class] alloc] init];
    
    //给"p1"这个对象动态添加一个属性:Key: name Vaule:lishijie,
    static char name;
    objc_setAssociatedObject(p1, &name, @"东方_未明", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    //获取"p1"这个对象属性为"name"的lishijie
    NSString * strName = objc_getAssociatedObject(p1, &name);
    //打印动态添加的属性
    NSLog(@"我是动态添加的属性:%@",strName);
    
}

/**
 *  通过类的名字,查看类中所有的方法
 *
 *  @param className 类的名字(egs:UIView)
 */
- (void)getMethodNameListWithClassName:(NSString *)className
{
    //如果想添加方法直接调用就行了(只需要改一下类)
    //添加方法
    [self addMethod];
    /**
     * class_copyMethodList:获取所有方法
     * method_getName:读取一个Method类型的变量,输出我们在上层中很熟悉的SEL
     *
     */
    
    //通过类的名字,获取到类
    Class ClassName = NSClassFromString(className);
    //定义一个变量来存放遍历出来类里面属性的个数
    unsigned int count = 0;
    //查取类里面所有的属性
    Method * method = class_copyMethodList(ClassName, &count);
    //遍历类里面所有的属性 和 属性类型
    for (int i = 0; i < count; i ++) {
        //获取类里面方法的名字
        SEL methodName = method_getName(method[i]);
        //获取类里面方法的类型
        const char * methodType = method_copyReturnType(method[i]);
        NSLog(@"方法名字:%@,方法类型:%s",NSStringFromSelector(methodName),methodType);
    }
    
    
}

/**
  class_addMethod的实现会覆盖父类的方法实现,但不会取代本类中已存在的实现,
如果本类中包含一个同名的实现,则函数会返回NO。

如果要修改已存在实现,可以使用method_setImplementation。
一个Objective-C方法是一个简单的C函数,它至少包含两个参数—self和_cmd。
所以,我们的实现函数(IMP参数指向的函数)至少需要两个参数
*/

//添加方法
- (void)addMethod
{
    //例如: 给UIView添加一个方法
    
    //给类添加一个方法
    id p1 = [NSString new];
    /**
     *  IMP指向的两个方法,必须实现(一个是函数的名字,一个是要实现的函数)
     *
     *  @param class]               类
     *  @param @selectormethod1Name 函数的名字
     *  @param IMPmethod1           要实现的函数
     *  @param "v@"                 函数参数的类型
     *
     *  @return void
     *
     */
    class_addMethod([NSString class], @selector(method1Name), (IMP)method1, "v@");
    //调用方法1
    [p1 method1Name];
    
}

//------------------------添加方法需要实现的--------------------------//
//方法的名字,没有实际的作用,只是标识类里面有这个函数
- (void)method1Name
{
    NSLog(@"我只是个method1名字");
}


//这个才是方法的实现  (根据method1Name  找到  method1 这个方法)
static void method1(id self, SEL _cmd, int a){
    NSLog(@"我是动态添加的method");
    
}


你可能感兴趣的:(runtime 基础篇(一))