gpt4 book ai didi

ios - Swizzling 不适用于类方法

转载 作者:行者123 更新时间:2023-11-28 18:55:14 24 4
gpt4 key购买 nike

Swizzling 不执行动态方法交换。这是我使用的代码。我听说这是一个无法在 xcode 7 中的 XCTest 中进行依赖注入(inject)的解决方案。你能给我解释一下 DI(依赖)上的 Swizzling 示例吗?

#import "TNUserDetail+Swizzle.h"
#import <objc/runtime.h>

@implementation TNUserDetail (Swizzle)

+ (void) swizzleInstanceSelector:(SEL)originalSelector
withNewSelector:(SEL)newSelector
{
Method originalMethod = class_getClassMethod(self, originalSelector);
Method newMethod = class_getClassMethod(self, newSelector);

BOOL methodAdded = class_addMethod([self class],
originalSelector,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod));

if (methodAdded) {
class_replaceMethod([self class],
newSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, newMethod);
}
}

+(BOOL)isSignUpSwizzle {

return sighUp;
}


Test
_____

@implementation TNSettingsViewControllerTests

- (void)setUp {
[super setUp];

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

self.settingVC = [sb instantiateViewControllerWithIdentifier:@"TNSettingsViewController"];


[self.settingVC performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
[self.settingVC performSelectorOnMainThread:@selector(viewWillAppear:) withObject:nil waitUntilDone:YES];
}

-(void)testTwitterConnectSwitchValueChanged
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

[TNUserDetail swizzleInstanceSelector:@selector(isSignUpWithTwitter) withNewSelector:@selector(isSignUpSwizzle)];
[TNUserDetail isSignUpWithTwitter];
});

sighUp = YES;
self.settingVC.twitterConnectSwitch.on = YES;
[self.settingVC.twitterConnectSwitch sendActionsForControlEvents:UIControlEventValueChanged];;
}

这里当我调用 [TNUserDetail isSignUpWithTwitter] 时,+(BOOL)isSignUpSwizzle 没有被调用,只有实际的方法被调用。怎么了。注意这两个方法都是类方法。

最佳答案

方法实例存在于调度表类中,但是调度表 meta_class 中存在类方法,因此您需要使用“元类”而不是 self(class)。

#import "TNUserDetail.h"
#import <objc/runtime.h>

@implementation TNUserDetail

+ (void)swizzleInstanceSelector:(SEL)originalSelector withNewSelector:(SEL)newSelector {
const char *className = [NSStringFromClass(self) UTF8String];
Class clazz = objc_getMetaClass(className);
Method originalMethod = class_getClassMethod(clazz, originalSelector);
Method newMethod = class_getClassMethod(clazz, newSelector);

BOOL methodAdded = class_addMethod(clazz,
originalSelector,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod));

if (methodAdded) {
class_replaceMethod(clazz,
newSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, newMethod);
}
}

+ (void)load {
[super load];
[self swizzleInstanceSelector:@selector(printHello) withNewSelector:@selector(printHelloWorld)];
}

+ (void)printHello {
NSLog(@"Hello");
}

+ (void)printHelloWorld {
NSLog(@"Hello World");
}

@end

并调用[TNUserDetail printHello];打印'Hello World'

但是你的调配影响了整个项目。对于这种情况,我建议使用部分模拟 (OCMock)

关于ios - Swizzling 不适用于类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34648815/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com