iOS开发中runtime常用使用示例

2,737 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

Runtime

Runtime即运行时,OC是一个拓展了C加入了面向对象和Smalltalk式消息传递的动态语言,实现这一点的核心便是Runtime库,这篇文章不去深入分析原理,仅简单粗暴的列出runtime在实际开发中的一些使用示例。

通过Associate为category添加属性

分类添加属性仅是一个声明,要做到存取需要使用runtime的Associate方法关联对象

  • 被关联的对象在生命周期内要比对象本身释放晚很多,它们会在NSObject -dealloc调用object_dispose()方法中释放。
  • 设置关联对象void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
    • object 被关联的对象
    • key 关联key 要求唯一
    • value 关联的对象
    • policy 缓存策略
  • 获取关联对象id objc_getAssociatedObject(id object, const void * key)
  • 移除关联对象void objc_removeAssociatedObjects(id object)
@interface UISlider (CQExtension)
/// 左右间距
@property (nonatomic, assign) CGFloat cq_margin;
@end
@implementation UISlider (CQExtension)
// 设置左右间距Setter
- (void)setCq_margin:(CGFloat)cq_margin {
    NSNumber *number = [NSNumber numberWithFloat:cq_margin];
    objc_setAssociatedObject(self, "cqMarginKey", number, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// 获取左右间距Getter
- (CGFloat)cq_margin {
    NSNumber *number = objc_getAssociatedObject(self, "cqMarginKey");
    return number ? [number floatValue] : 0.0f;
}
@end

通过class_copyPropertyList获取属性

/// 获取对象所有的属性
- (NSArray <NSDictionary *>*)cq_getPropertylist {
    NSMutableArray *arr = [NSMutableArray array];
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);
    for (int i =0; i<count; i++) {
        objc_property_t property = propertyList[i];
        const char *name = property_getName(property);
        NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
        [arr addObject:nameStr];
    }
    free(propertyList);
    return [arr copy];
}

/// 获取对象所有的属性
+ (NSArray <NSDictionary *>*)cq_getPropertylistWithObject:(NSObject *)object {
    return [object cq_getPropertylist];
}


//获取对象所有属性及属性的值  key(属性)=value(值)
- (NSArray <NSDictionary *>*)cq_getPropertyAndValueList {
    NSMutableArray *arr = [NSMutableArray array];
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);
    for (int i =0; i<count; i++) {
        objc_property_t property = propertyList[i];
        const char *name = property_getName(property);
        NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
        NSString *value = [self valueForKey:nameStr];
        NSDictionary *dic = @{nameStr:value?value:@"-nil-"};
        [arr addObject:dic];
    }
    free(propertyList);
    return [arr copy];
}

+ (NSArray <NSDictionary *>*)cq_getPropertyAndValueListWithObject:(NSObject *)object {
    return [object cq_getPropertyAndValueList];
}

通过class_copyMethodList获取所有方法

// 获取对象所有的方法
- (NSArray *)cq_getMethodlist {
    NSMutableArray *arr = [NSMutableArray array];
    unsigned int count = 0;
    Method *methodList = class_copyMethodList([self class], &count);
    for (int i =0; i<count; i++) {
        Method method = methodList[i];
        SEL sel =  method_getName(method);
        const char *methodName = sel_getName(sel);
        NSString *methodStr = [[NSString alloc] initWithUTF8String:methodName];
        [arr addObject:methodStr];
    }
    free(methodList);
    return [arr copy];
}

/// 获取对象所有的方法
+ (NSArray *)cq_getMethodlistWithObject:(NSObject *)object {
    return [object cq_getMethodlist];
}

通过class_copyIvarList获取所有成员变量

//获取对象所有的成员变量
- (NSArray *)cq_getIvarlist {
    NSMutableArray *arr = [NSMutableArray array];
    unsigned int count = 0;
    Ivar *propertyList = class_copyIvarList([self class], &count);
    for (int i =0; i<count; i++) {
        Ivar property = propertyList[i];
        const char *name = ivar_getName(property);
        NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
        [arr addObject:nameStr];
    }
    free(propertyList);
    return [arr copy];
}

+ (NSArray *)cq_getIvarlistWithObject:(NSObject *)object {
    return [object cq_getIvarlist];
}

实例方法交换

/**
 实例方法交换
 @param oriCls 原类
 @param origSel 原函数
 @param altCls 新类
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleMethodOriCls:(Class)oriCls origSel:(SEL)origSel swizzCls:(Class)altCls swizzSel:(SEL)altSel {
    Method origMethod = class_getInstanceMethod(oriCls, origSel);
    Method altMethod = class_getInstanceMethod(altCls, altSel);
    if (!origMethod || !altMethod) {
        return NO;
    }
    BOOL didAddMethod = class_addMethod(oriCls,origSel,method_getImplementation(altMethod),method_getTypeEncoding(altMethod));
    if (didAddMethod) {
        class_replaceMethod(altCls,altSel,method_getImplementation(origMethod),method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, altMethod);
    }
    return YES;
}

/**
 实例方法交换
 @param cls 需要交换的类
 @param origSel 原函数
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleMethod:(Class)cls origSel:(SEL)origSel swizzSel:(SEL)altSel {
    return [self cq_swizzleMethodOriCls:cls origSel:origSel swizzCls:cls swizzSel:altSel];
}

/**
 实例方法交换,直接交换本类
 @param origSel 原函数
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleMethodOrigSel:(SEL)origSel swizzSel:(SEL)altSel {
    return [self cq_swizzleMethod:[self class] origSel:origSel swizzSel:altSel];
}

类方法交换

/**
 类方法交换
 @param cls 原类
 @param origSel 原函数
 @param altCls 新类
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleClassMethodOriCls:(Class)oriCls origSel:(SEL)origSel swizzCls:(Class)altCls swizzSel:(SEL)altSel {
    Method origMethod = class_getClassMethod(oriCls, origSel);
    Method altMethod = class_getClassMethod(altCls, altSel);
    if (!origMethod || !altMethod) {
        return NO;
    }
    BOOL didAddMethod = class_addMethod(object_getClass(oriCls),origSel,method_getImplementation(altMethod),method_getTypeEncoding(altMethod));
    if (didAddMethod) {
        class_replaceMethod(altCls,altSel,method_getImplementation(origMethod),method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, altMethod);
    }
    return YES;

}

/**

 类方法交换
 @param cls 需要交换的类
 @param origSel 原函数
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleClassMethod:(Class)cls origSel:(SEL)origSel swizzSel:(SEL)altSel {
    return [self cq_swizzleClassMethodOriCls:cls origSel:origSel swizzCls:cls swizzSel:altSel];
}

/**
 类方法交换,直接交换本类
 @param origSel 原函数
 @param altSel 新函数
 */
+ (BOOL)cq_swizzleClassMethodOrigSel:(SEL)origSel swizzSel:(SEL)altSel {
    return [self cq_swizzleClassMethod:[self class] origSel:origSel swizzSel:altSel];
}