Re: Forcing allocation of a subclass
Re: Forcing allocation of a subclass
- Subject: Re: Forcing allocation of a subclass
- From: Jean-Daniel Dupas <email@hidden>
- Date: Sat, 24 Jan 2009 19:39:21 +0100
Le 24 janv. 09 à 19:20, Bill Bumgarner a écrit :
Thanks. I found that a few hours ago and was able to create the
exchange. However, writing a correct replacement method is another
thing altogether. The following doesn't work:
Early in application startup:
Method originalMethod = class_getClassMethod([PDFDocument class],
@selector(alloc));
Method replacedMethod = class_getClassMethod([PDFDocument class],
@selector(allocReplacement));
method_exchangeImplementations(originalMethod, replacedMethod);
Addition to PDFDocument:
+ (id)allocReplacement
{
if ([[self class] isEqual:[PDFDocument class]]) {
return [ANPDFDocument alloc];
} else {
return [super alloc];
}
}
I get the impression it replaces alloc for everything, not just for
the PDFClerkDocument class. So the app crashes immediately after
the implementation exchange. Which doesn't surprise me really. But:
Is there a way to make this work using
method_exchangeImplementations, or maybe for the particular problem
at hand, is there a better way of making the PDFThumbnailView use
the correct PDFDocument (sub)class when it deals with multiple
selections.
Just to make this clear: I would really rather not create this
workaround, but I can't really afford not to let users drag
multiple pages in the PDFClerkThumbnailView either.
Ahh... yes -- my suggestion was slightly misleading.
class_getClassMethod() will walk the class hierarchy and return a
super's implementation, if the method itself is not found in the
subclass.
This is expected, and not a problem with exchange implementation.
You'll need to detect whether or not the method already exists in
the targeted class. You can use class_copyMethodList() to grab the
methods specific to the class and then hunt about within to see if
the targeted method is implemented.
Not require here, but my way to do this is the following one:
Method originalMethod = class_getClassMethod([PDFDocument class],
@selector(allocWithZone:));
Method superMethod =
class_getClassMethod(class_getSuperclass([PDFDocument class]),
@selector(allocWithZone:));
if (superMethod == originalMethod) {
// PDF Document does not override allowWithZone:
}
If so, the method_exchangeImplementations() pattern will work. If
not, you'll need to add the method to the class via class_addMethod().
Normally, when doing this kind of thing, you absolutely positively
must call the original implementation of the method -- whether it be
in the class or in the superclass -- to ensure that you preserve any
existing behaviors.
Yes, but to call the original impl, you don't use super. You call
[self allocReplacement]
+alloc, though, is slightly different in that classes typically only
override +alloc when they want to do some kind of custom allocation
behavior and, by doing so, they would almost never (but not never)
call through to super's implementation.
And so, exchanging alloc is not different than exchanging any other
method.
If you are actually replacing +alloc (which, in this case, it seems
not), well.... that can be very very tricky.
b.bum
_______________________________________________
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