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 (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