Skip to content

Instantly share code, notes, and snippets.

@cdzombak
Created January 4, 2013 17:16
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdzombak/4454286 to your computer and use it in GitHub Desktop.
Save cdzombak/4454286 to your computer and use it in GitHub Desktop.
Separate concerns. `UIScrollViewDelegate` deals with a container, while `UITableViewDelegate` deals with content. It's often useful to have two different objects manage these concerns, but Cocoa Touch makes it difficult since `UITableViewDelegate` conforms to `UIScrollViewDelegate` and `UITableView` has only one delegate property. `CDZTableViewS…
#import <Foundation/Foundation.h>
@interface CDZTableViewSplitDelegate : NSObject <UIScrollViewDelegate, UITableViewDelegate>
@property (nonatomic, weak) id<UITableViewDelegate> tvDelegate;
@property (nonatomic, weak) id<UIScrollViewDelegate> svDelegate;
- (id)initWithScrollViewDelegate:(id<UIScrollViewDelegate>)scrollViewDelegate tableViewDelegate:(id<UITableViewDelegate>)tableViewDelegate;
@end
#import "CDZTableViewSplitDelegate.h"
#import <objc/runtime.h> // shit just got real
@implementation CDZTableViewSplitDelegate
- (id)initWithScrollViewDelegate:(id<UIScrollViewDelegate>)scrollViewDelegate
tableViewDelegate:(id<UITableViewDelegate>)tableViewDelegate
{
self = [super init];
if (self) {
self.svDelegate = scrollViewDelegate;
self.tvDelegate = tableViewDelegate;
}
return self;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if ([self selectorIsPartOfUIScrollViewDelegate:aSelector]) {
return self.svDelegate;
}
if ([self selectorIsPartOfUITableViewDelegate:aSelector]) {
return self.tvDelegate;
}
return [super forwardingTargetForSelector:aSelector];
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
id forwardingTarget = [self forwardingTargetForSelector:aSelector];
if (forwardingTarget == self.tvDelegate || forwardingTarget == self.svDelegate) {
return [forwardingTarget respondsToSelector:aSelector];
}
return [super respondsToSelector:aSelector];
}
- (BOOL)selectorIsPartOfUIScrollViewDelegate:(SEL)aSelector
{
// assuming all UIScrollViewDelegate methods are instance methods
return [self selector:aSelector isInstanceMethodForProtocol:@protocol(UIScrollViewDelegate)];
}
- (BOOL)selectorIsPartOfUITableViewDelegate:(SEL)aSelector
{
// assuming all UITableViewDelegate methods are instance methods
return [self selector:aSelector isInstanceMethodForProtocol:@protocol(UITableViewDelegate)];
}
- (BOOL)selector:(SEL)aSelector isInstanceMethodForProtocol:(Protocol *)p
{
if ([self selector:aSelector isInstanceMethodForProtocol:p required:YES]) return YES;
else return [self selector:aSelector isInstanceMethodForProtocol:p required:NO];
}
- (BOOL)selector:(SEL)aSelector isInstanceMethodForProtocol:(Protocol *)p required:(BOOL)isRequired
{
NSParameterAssert(p != NULL);
struct objc_method_description methodDesc = protocol_getMethodDescription(p, // protocol
aSelector, // selector
isRequired, // whether selector represents a required method
YES // whether selector represents an instance method
);
return (methodDesc.name) ? YES : NO;
}
@end
@eHomeTechnology
Copy link

not quite understand, how to use it?

@geraldWilliam
Copy link

Thank you for this. Totally helped me out today.

@ULazdins
Copy link

ULazdins commented Dec 5, 2019

For those looking for Swift version - here you go: https://gist.github.com/ULazdins/71a2bfd474c7f6fe9d0e61a749271247

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment