Re: Forcing allocation of a subclass
Re: Forcing allocation of a subclass
- Subject: Re: Forcing allocation of a subclass
- From: Bill Bumgarner <email@hidden>
- Date: Sat, 24 Jan 2009 10:20:07 -0800
On Jan 24, 2009, at 9:51 AM, Antonio Nunes wrote:
On 24 Jan 2009, at 18:09, Bill Bumgarner wrote:
Or, more specifically, why do you want to make some bit of
framework code which currently allocates an instance of A allocate
an instance of SubA instead?
Because of, what I assume to be, a bug in PDFClerkThumbnailView
which when one drags multiple pages from or within it, puts the
pages in a PDFDocument instead of in the subclass of PDFDocument,
which is where the pages live. Dragging a single page works as
expected and the page is of the correct subclass. Dragging multiple
pages leads to errors. I filed a bug report for this a while back,
but I really need a safe workaround until the issue is fixed.
(Assuming Apple considers it a bug too. I have never received
feedback on it.)
OK -- I would encourage you to be as defensive as possible in your
coding of a workaround for this bug.
Check to make sure that the classes and methods are all implemented /
not implemented in a way that your code expects.
Ideally, if you can programmatically detect the problematic behavior,
do so and verify its presence prior to mucking about with the innards
of the PDF* classes.
I would use method_exchangeImplementations(), if absolutely
positively necessary. It is about the most innocuous of an
otherwise noxious encapsulation breaking implementation pattern.
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.
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.
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.
+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.
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