Cannot use swizzle class methods

I am working on a plugin for Mail.app. I want the plugin to add a button to the Mail toolbar. For this, I decided that the best approach would be to call a function to add this button to the MessageViewer initialization method (MessageViewer is the class for Mail.app FirstResponder). The code I'm modifying seems to work well:

+ (void) initialize { [super initialize]; // class_setSuperclass([self class], NSClassFromString(@"MVMailBundle")); // [ArchiveMailBundle registerBundle]; // Add a couple methods to the MessageViewer class. Class MessageViewer = NSClassFromString(@"MessageViewer"); // swizzleSuccess should be NO if any of the following three calls fail BOOL swizzleSuccess = YES; swizzleSuccess &= [[self class] copyMethod:@selector(_specialValidateMenuItem:) fromClass:[self class] toClass:MessageViewer]; swizzleSuccess &= [[self class] copyMethod:@selector(unsubscribeSelectedMessages:) fromClass:[self class] toClass:MessageViewer]; 

However, when I try to do the same, it does not work:

 // //Copy the method to the original MessageViewer swizzleSuccess &= [[self class] copyMethod:@selector(_specialInitMessageViewer:) fromClass:[self class] toClass:MessageViewer]; 

Here are the swizzling methods:

 + (BOOL)swizzleMethod:(SEL)origSel withMethod:(SEL)altSel inClass:(Class)cls { // For class (cls), swizzle the original selector with the new selector. //debug lines to try to figure out why swizzling is failing. // if (!cls || !origSel) { // NSLog(@"Something was null. Uh oh."); //} Method origMethod = class_getInstanceMethod(cls, origSel); if (!origMethod) { NSLog(@"Swizzler -- original method %@ not found for class %@", NSStringFromSelector(origSel), [cls className]); return NO; } //if (!altSel) NSLog(@"altSel null. :("); Method altMethod = class_getInstanceMethod(cls, altSel); if (!altMethod) { NSLog(@"Swizzler -- alternate method %@ not found for class %@", NSStringFromSelector(altSel), [cls className]); return NO; } method_exchangeImplementations(origMethod, altMethod); return YES; } + (BOOL) copyMethod:(SEL)sel fromClass:(Class)fromCls toClass:(Class)toCls { // copy a method from one class to another. Method method = class_getInstanceMethod(fromCls, sel); if (!method) { NSLog(@"copyMethod-- method %@ could not be found in class %@", NSStringFromSelector(sel), [fromCls className]); return NO; } class_addMethod(toCls, sel, class_getMethodImplementation(fromCls, sel), method_getTypeEncoding(method)); return YES; } 

It seems that an error occurs in the call to class_getInstanceMethod, because I get an error message in the log. This happens for both the method inside my own class and the MessageViewer initialization method.

Are there any errors that I do not take into account here?

+4
source share
2 answers

Instead of trying to do the swizzling manually, you should just use JRSwizzle . One caveat, the implementation of JSRwizzle +jr_swizzleClassMethod:withClassMethod:error: is just a stub, but instead you can just call +jr_swizzleMethod:withMethod:error in the class metaclass (e.g. just pass klass->isa instead of klass (where klass is class that you are 'swizzling)).

+5
source

If you want to swizzle class methods, why are you using class_getInstanceMethod() instead of class_getClassMethod() ?

+9
source

All Articles