Method exchange is dangerous because if the target class (NSConcreteNotification) does not override the target function (dealloc), you may exchange it's superclass dealloc method instead and may end up overriding a method in a base class. Use it with great care and avoid it in production code if possible.
Le 12 mars 2010 à 03:00, Gideon King a écrit : > 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 gpar...@apple.com Runtime Wrangler > > > _______________________________________________ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > 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: > http://lists.apple.com/mailman/options/cocoa-dev/devlists%40shadowlab.org > > This email sent to devli...@shadowlab.org -- Jean-Daniel _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com