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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to