我需要为需要扩展的方法添加其他行为,即实现类似于
的方法- (void)extendMethod:(SEL)selector forClass:(Class)class withCompletionBlock:(void (^)(void))completionBlock;
因此,每次Class
实例调用带有SEL
选择器的方法时,都应调用我的完成块。
我尝试过方法调整,但遇到了一些问题:我希望调用原始方法实现。
我需要的是与子类化非常相似,但是应该实现而不进行子类化。
更新
例如,我有UIViewController
的子类,名为MyViewController
。 MyViewController
有- (void)viewDidLoad
方法。在应用程序的某处我调用方法
[methodExtender extendMethod:@selector(viewDidLoad)
forClass:[MyViewController class]
withCompletionBlock:^{
NSLog(@"view did load called");
}];
所以在MyViewController的每个实例的viewDidLoad方法之后调用我的完成块。
答案 0 :(得分:1)
我不确定你想如何使用选择器,但是你可以尝试使用Objective-C中的机制来扩展任何类(甚至是那些你没有实现文件的类)。
Xcode将创建两个文件,例如:UIButton+extendMethod.h
在头文件中声明您的方法并在* .m文件中实现它。
是强>
如果您想使用,请在* .h文件导入中说明您的View Controller
#import "UIButton+extendMethod.h"
然后你可以像这样调用你的方法:
UIButton *button = [[UIButton alloc] init];
[button extendMethod:@selector(yourMethod:)];
答案 1 :(得分:0)
Swizzling确实允许你调用原始实现,虽然它有点令人困惑。因为实现是在调配后交换的,所以使用swizzled方法的选择器调用原始实现:
- (void)mySwizzledImplementation {
// do stuff
// now call original implementation (using swizzled selector!)
[self mySwizzledImplementation];
// do more stuff
}
答案 2 :(得分:0)
在没有子类化的情况下,没有办法(不再)模拟继承。有使用Posing,方法调整就是剩下的东西(虽然不像摆姿势那样优雅)。这是在能够调用原始实现时正确调整方法的一种方法。
int swizzle_instance_methods(Class class, SEL selector, IMP replacement, IMP *store) {
@synchronized(class) {
Method method = class_getInstanceMethod(class, selector);
IMP original_imp = NULL;
if (method != NULL) {
const char *type = method_getTypeEncoding(method);
IMP original_imp = class_replaceMethod(class, selector, replacement, type);
if (original_imp == NULL)
original_imp = method_getImplementation(method);
if (original_imp != NULL && store != NULL) {
*store = original_imp;
}
}
return (original_imp != NULL);
}
}
+ (void) load
{
static IMP originalMethodImpl = NULL;
IMP customMethodImpl = imp_implementationWithBlock(^(id self_) {
NSString *descr = ((NSString(*)(id,SEL))originalMethodImpl)(self_, @selector(description);
return [NSString stringWithFormat:@"<--- %@ --->",descr];
});
swizzle_instance_methods([self class], @selector(description), customMethodImpl, &originalMethodImpl);
}
我可能会补充一点,这对于调试很有用,我认为它可以用于构建优秀的框架。唉,Apple似乎有不同的想法,使用方法调配会导致您的应用程序被排除在App Store之外。如果您不是针对应用程序商店,那么所有权力都可以为您服务。
答案 3 :(得分:0)
可以使用ObjC类别。例如,您可以扩展NSString的hasPrefix方法,如下所示,
-(BOOL)hasPrefixx:(NSString *)aString
{
NSLog(@"Checking has prefix");
return [self hasPrefix:aString];
}
如果您导入类别,则应该可以调用此方法。但他的意思是你改变了你的电话中的方法。
顺便说一句,Method swizzling应该可行。一点点解释here。