私は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 メソッドは完全に機能します。