运行时运用

一 , 设置关联属性
分类中设置属性进行关联判断(其中SDWebimage中用到过)
/**
 * 下载图像的 URL 字符串
 * 一个属性:分类中不能有 ivar(成员变量) / getter / setter
 */
const char *jq_URLStringKey = "jq_URLStringKey";

@property (nonatomic, copy) NSString *jq_urlString;

- (NSString *)jq_urlString {
    //利用运行时记录属性
    return objc_getAssociatedObject(self, jq_URLStringKey);
}

- (void)setJq_urlString:(NSString *)jq_urlString {
   
    objc_setAssociatedObject(self, jq_URLStringKey, jq_urlString, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
二, 运行时动态调用方法(在OC与JS的交互中用到)
#import 

1 > 调用无返回值的方法
参数一位当前调用方法对象
参数二为方法对象
参数三为需要传递的参数
下面是最基本的调用格式
SEL sel = NSSelectorFromString(methodName);
((void(*)(id, SEL, id))objc_msgSend)(self, sel, parameter);

2 > 调用有返回值的方法
 NSString *result = ((NSString *(*)(id, SEL, id, id, id))objc_msgSend)(self, sel, parameter, parameter2, parameter3);

- (NSString *)showFood1:(NSString *)food1 Food2:(NSString *)food2 Food3:(NSString *)food3 {
   
    NSLog(@"%@ -- %@ -- %@", food1, food2, food3);
    return @"delicious";
}
3 > 调用类方法, 需要将类转为类对象
    Class personClass = [Person class];
   
    [personClass performSelector:@selector(drink)];
    ((void(*)(id, SEL))objc_msgSend)(personClass, @selector(drink));
三, 动态获取类的属性和成员变量(字典转模型或KVC改变系统属性变量)
const void *propertyListKey = @"propertyListKey";

+ (NSArray *)jq_propertyList {
   
    // 0. --- 判断属性数组是否存在,如果存在直接返回 `属性数组对象` ---
    NSArray *result = objc_getAssociatedObject(self, propertyListKey);
   
    if (result != nil) {
        return result;
    }
   
    // 1. 获取属性数组
    unsigned int count = 0;
    objc_property_t *list = class_copyPropertyList([self class], &count);
   
    NSLog(@"属性数量 %u", count);
   
    NSMutableArray *arrM = [NSMutableArray array];
    // 2. 遍历数组
    for (unsigned int i = 0; i < count; i++) {
       
        // 1> 通过下标获取属性对象
        objc_property_t property = list[i];
       
        // 2> 获取属性的名称
        const char *pty = property_getName(property);
       
        // 3> 转换成 OC 的字符串
        NSString *str = [NSString stringWithUTF8String:pty];
       
        [arrM addObject:str];
    }
   
    //释放数组
    free(list);
   
    // --- 保存属性数组对象 ---
    objc_setAssociatedObject(self, propertyListKey, arrM, OBJC_ASSOCIATION_COPY_NONATOMIC);
   
    return arrM.copy;
}

+ (NSArray *)jq_ivarList {
   
    // 1. 取类的成员变量列表
    unsigned int count = 0;
    Ivar *list = class_copyIvarList([self class], &count);
   
    // NSLog(@"%u", count);
    NSMutableArray *arrayM = [NSMutableArray array];
   
    // 2. 遍历数组
    for (unsigned int i = 0; i < count; i++) {
       
        // 1> 根据下标获取成员变量
        Ivar ivar = list[i];
       
        // 2> 取 ivar 的名字
        const char *cName = ivar_getName(ivar);
       
        // 3> 转换成 NSString
        NSString *name = [NSString stringWithUTF8String:cName];
       
        [arrayM addObject:name];
    }
   
    // 3. 释放列表
    free(list);
   
    return arrayM.copy;
}
四, 动态交换方法(在AFNetworking中 URLSession 做了一个交叉方法, 交换了系统的resume 方法, 以便在系统调用时可以发送一个通知来监听方法实现)
+ (void)load {

    Method originalMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method swizzledMethod = class_getClassMethod([UIImage class], @selector(jq_imageNamed:));

    //交换方法
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

+ (UIImage *)jq_imageNamed:(NSString *)imageName {
   
    // 1, 加载图片
    UIImage *image = [UIImage jq_imageNamed:imageName];
   
    // 2, 判断功能
    if (image == nil) {
        NSLog(@" image == nil");
    }
    return image;
}
五, 动态添加方法(不常用)
void laugh(id self, SEL _cmd, id param) {
   
    NSLog(@"%@ - %@ - %@", self, NSStringFromSelector(_cmd), param);
}
//当调用了没有实现的方法就会调用
+ (BOOL)resolveInstanceMethod:(SEL)sel {
   
    NSLog(@"%@", NSStringFromSelector(sel));
   
    //动态添加laugh方法
    if (sel == @selector(laugh:)) {
       
        /*
         Class:   给哪个类添加
         SEL:     方法编号
         IMP:     方法实现, 函数名
         types:   方法类型 v -> void  @ -> 第一个参数 表示id类型  : -> 代码SEL 方法
         */
        class_addMethod(self, sel, (IMP)laugh, "v@:@");
       
        //处理完
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

你可能感兴趣的:(运行时运用)