Re: Switching methods in private classes in Apple frameworks
Re: Switching methods in private classes in Apple frameworks
- Subject: Re: Switching methods in private classes in Apple frameworks
- From: Gideon King <email@hidden>
- Date: Fri, 12 Mar 2010 12:00:53 +1000
This is really cool...so I can replace a method without being a subclass or category.
So I implemented an NSObject subclass with the new method, and did the method exchange, and my new method was called instead of the old one, but I had a problem - the call to the switched out method (dealloc from the NSConcreteNotification) didn't work. I assumed that was because the old implementation of dealloc was now moved to my class, so I changed the method switching so that it ensures that the old dealloc is replaced with the implementation of mydealloc, and that I have added a method to the NSConcreteNotification which is called mydealloc, and does the things that the old dealloc did.
This seems to work, so I thought I'd post it here in case anyone else needs to replace a method in a private class, and be able to call the original implementation.
#import <objc/runtime.h>
#import <Cocoa/Cocoa.h>
@interface MyConcreteNotification : NSObject {
}
- (void)mydealloc;
@end
@implementation MyConcreteNotification
+ (void)load {
Method originalMethod = class_getInstanceMethod(NSClassFromString(@"NSConcreteNotification"), @selector(dealloc));
Method replacedMethod = class_getInstanceMethod(self, @selector(mydealloc));
IMP imp1 = method_getImplementation(originalMethod);
IMP imp2 = method_getImplementation(replacedMethod);
// Set the implementation of dealloc to mydealloc
method_setImplementation(originalMethod, imp2);
// Add a mydealloc method to the NSConcreteNotification with the implementation as per the old dealloc method
class_addMethod(NSClassFromString(@"NSConcreteNotification"), @selector(mydealloc), imp1, NULL);
}
- (void)mydealloc {
NSLog(@"My concrete notification is being deallocated");
NSLog(@"Name: %@\nObject: %@\nUser Info: %@\n", [self name], [self object], [self userInfo]);
// Call the original method, whose implementation was exchanged with our own.
// Note: this ISN'T a recursive call, because this method should have been called through dealloc.
NSParameterAssert(_cmd == @selector(dealloc));
[self mydealloc];
}
@end
Regards.
Gideon
>
> On iPhone and 64-bit Mac, the linker enforces internal classes more strictly. NSConcreteNotification is private, so you can't link to it or subclass it. You can still get the class via runtime introspection like NSClassFromString(), which for debugging purposes ought to be good enough.
> --
> Greg Parker email@hidden Runtime Wrangler
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden