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

Reply via email to