所有子类的Swizzle方法

时间:2015-03-31 11:44:06

标签: ios objective-c swizzling

我有CLLocationManager类,方法为setDelegate:。我在封闭框架中也有继承类。我想为这个类和所有继承交换实现setDelegate:

NSArray *sfl_classGetSubclasses(Class parentClass) {
    int numClasses = objc_getClassList(NULL, 0);
    Class *classes = NULL;

    classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
    numClasses = objc_getClassList(classes, numClasses);

    NSMutableArray *result = [NSMutableArray array];
    for (NSInteger i = 0; i < numClasses; i++) {
        Class superClass = classes[i];
        do {
            superClass = class_getSuperclass(superClass);
        } while(superClass && superClass != parentClass);

        if (superClass == nil) {
            continue;
        }

        [result addObject:classes[i]];
    }
    free(classes);
    return result;
}

@implementation CLLocationManager (SimulateFakeLocations)

+ (void)initialize {
    [self swizzleSelector:@selector(setDelegate:) class1:self withSelector:@selector(sfl_setDelegate:) class2:self];
    NSArray *subclasses = sfl_classGetSubclasses(self); // I get empty array
    for (Class cl in subclasses) {
        [self swizzleSelector:@selector(setDelegate:) class1:cl withSelector:@selector(sfl_setDelegate:) class2:self];
    }
}

+ (void)swizzleSelector:(SEL)sel1 class1:(Class)class1 withSelector:(SEL)sel2 class2:(Class)class2
{
    Method originalMethod = class_getInstanceMethod(class1, sel1);
    Method swizzledMethod = class_getInstanceMethod(class2, sel2);

    BOOL didAddMethod = class_addMethod(class1,
                                        sel1,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class2,
                            sel2,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}
// ...
@end

但我没有得到任何子类sfl_classGetSubclasses。这是第一个问题。第二:我知道子类的名称,我尝试在inhered类中交换方法。

Class cl = NSClassFromString(@"YMKLocationManager");
[self swizzleSelector:@selector(setDelegate:) class1:cl withSelector:@selector(sfl_setDelegate:) class2:self];

但是应用程序在运行时会下降。直到我使用封闭框架,交换方法才能完美运行。

0 个答案:

没有答案