3

私は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。これが最初の問題です。2番目: サブクラスの名前を知っていて、継承されたクラスでメソッドを交換しようとします。

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

しかし、アプリケーションは実行時に落ちます。クローズド フレームワークを使用するまでは、exchange メソッドは完全に機能します。

4

0 に答える 0