-
-
Save steipete/2871154 to your computer and use it in GitHub Desktop.
This was nice and fast... but it takes up WAY TOO MUCH space. And it's annoying to write. | |
(I like the way I can just step into the function that calls the delegate for debugging) | |
What's a better way to not make me call respondsToSelector in the middle of my code? Some proxy? | |
struct { | |
unsigned int delegateWillDisplayDocument:1; | |
unsigned int delegateDidDisplayDocument:1; | |
unsigned int delegateDidShowPageView:1; | |
unsigned int delegateDidRenderPageView:1; | |
unsigned int delegateDidChangeViewMode:1; | |
unsigned int delegateDidTapOnPageView:1; | |
unsigned int delegateDidTapOnAnnotation:1; | |
unsigned int delegateShouldDisplayAnnotation:1; | |
unsigned int delegateViewForAnnotation:1; | |
unsigned int delegateAnnotationViewForAnnotation:1; | |
unsigned int delegateWillShowAnnotationView:1; | |
unsigned int delegateDidShowAnnotationView:1; | |
unsigned int delegateDidLoadPageView:1; | |
unsigned int delegateWillUnloadPageView:1; | |
unsigned int delegateDidEndPageScrollingAnimation:1; | |
unsigned int delegateDidEndZoomingAtScale:1; | |
unsigned int delegateWillShowControllerAnimated:1; | |
unsigned int delegateDidShowControllerAnimated:1; | |
} delegateFlags_; | |
- (void)setDelegate:(id<PSPDFViewControllerDelegate>)delegate { | |
if (delegate != delegate_) { | |
delegate_ = delegate; | |
delegateFlags_.delegateWillDisplayDocument = [delegate respondsToSelector:@selector(pdfViewController:willDisplayDocument:)]; | |
delegateFlags_.delegateDidDisplayDocument = [delegate respondsToSelector:@selector(pdfViewController:didDisplayDocument:)]; | |
delegateFlags_.delegateDidShowPageView = [delegate respondsToSelector:@selector(pdfViewController:didShowPageView:)]; | |
delegateFlags_.delegateDidRenderPageView = [delegate respondsToSelector:@selector(pdfViewController:didRenderPageView:)]; | |
delegateFlags_.delegateDidChangeViewMode = [delegate respondsToSelector:@selector(pdfViewController:didChangeViewMode:)]; | |
delegateFlags_.delegateDidTapOnPageView = [delegate respondsToSelector:@selector(pdfViewController:didTapOnPageView:info:coordinates:)]; | |
delegateFlags_.delegateDidTapOnAnnotation = [delegate respondsToSelector:@selector(pdfViewController:didTapOnAnnotation:page:info:coordinates:)]; | |
delegateFlags_.delegateShouldDisplayAnnotation = [delegate respondsToSelector:@selector(pdfViewController:shouldDisplayAnnotation:onPageView:)]; | |
delegateFlags_.delegateViewForAnnotation = [delegate respondsToSelector:@selector(pdfViewController:viewForAnnotation:onPageView:)]; | |
delegateFlags_.delegateAnnotationViewForAnnotation = [delegate respondsToSelector:@selector(pdfViewController:annotationView:forAnnotation:onPageView:)]; | |
delegateFlags_.delegateWillShowAnnotationView = [delegate respondsToSelector:@selector(pdfViewController:willShowAnnotationView:onPageView:)]; | |
delegateFlags_.delegateDidShowAnnotationView = [delegate respondsToSelector:@selector(pdfViewController:didShowAnnotationView:onPageView:)]; | |
delegateFlags_.delegateDidLoadPageView = [delegate respondsToSelector:@selector(pdfViewController:didLoadPageView:)]; | |
delegateFlags_.delegateWillUnloadPageView = [delegate respondsToSelector:@selector(pdfViewController:willUnloadPageView:)]; | |
delegateFlags_.delegateDidEndPageScrollingAnimation = [delegate respondsToSelector:@selector(pdfViewController:didEndPageScrollingAnimation:)]; | |
delegateFlags_.delegateDidEndZoomingAtScale = [delegate respondsToSelector:@selector(pdfViewController:didEndPageZooming:atScale:)]; | |
delegateFlags_.delegateWillShowControllerAnimated = [delegate respondsToSelector:@selector(pdfViewController:willShowController:embeddedInController:animated:)]; | |
delegateFlags_.delegateDidShowControllerAnimated = [delegate respondsToSelector:@selector(pdfViewController:didShowController:embeddedInController:animated:)]; | |
} | |
} | |
- (void)delegateWillDisplayDocument { | |
if (delegateFlags_.delegateWillDisplayDocument) { | |
[self.delegate pdfViewController:self willDisplayDocument:self.document]; | |
} | |
} | |
- (void)delegateDidDisplayDocument { | |
if(delegateFlags_.delegateDidDisplayDocument) { | |
[self.delegate pdfViewController:self didDisplayDocument:self.document]; | |
} | |
} | |
(etc, etc) |
a macro or a simple function or method would look good and could even use the caching (don't know If Id want that though)...
anyways :) id be interested in hearing what you finally decide on
I prefer to check the respondsToSelector in place. Generally rather dislike such caches. I usually don't have that much delegate methods though...
However, you could build a proxy class that assembles method implementations automatically using runtime calls. That'd be extremely elegant, albeit a bit of work and probably shooting with canons on pigeons. You could open-source it afterwards though ;)
No proxy tricks, but FWIW I use ids directly:
struct
{
id willDisplayDocumentDelegate;
id didDisplayDocumentDelegate;
// etc.
} _delegates;
- (void)setDelegate:(id <PSPDFViewControllerDelegate>)delegate
{
if (delegate)
{
if ([delegate respondsToSelector:@selector(pdfViewController:willDisplayDocument:)])
_delegates.willDisplayDocumentDelegate = delegate;
if ([delegate respondsToSelector:@selector(pdfViewController:didDisplayDocument:)])
_delegates.didDisplayDocumentDelegate = delegate;
// etc.
}
else
memset(_delegates, 0, sizeof(_delegates));
}
- (void)delegateWillDisplayDocument
{
[_delegates.willDisplayDocumentDelegate pdfViewController:self willDisplayDocument:self.document];
}
- (void)delegateDidDisplayDocument
{
[delegates_.didDisplayDocumentDelegate pdfViewController:self didDisplayDocument:self.document];
}
// etc.
I like your approach, @hatfinch, but should the zeroing of the _delegates table not should happen first, and unconditionally, as the if
statements only set the fields for methods that are present in the new delegate. If there was a previous setting for a field and the new delegate doesn't implement that method, the old value would still be present (causing the old delegate to be called for some methods).
Also, I believe that object refs in a struct are no longer allowed under ARC, but (__weak
) ivars could work just as well.
-forwardingTargetForSelector:
, because if nothing happens there, the runtime will try-forwardInvocation:
.