Generic UITableViewDelegate

I am writing a subclass of UITableView and want my subclass to process some of the UITableViewDelegate methods before passing them along with the β€œreal” delegate, as well as redirect all UITableViewDelegate methods not implemented by my subclass.

In a subclass, I have a private property:

@property (nonatomic, assign) id <UITableViewDelegate> trueDelegate; 

which contains the "real delegate" to which all unrealized methods should pass. In both my init methods, I set

 self.delegate = self; 

and I override - (void) setDelegate: (id) like this

 -(void)setDelegate:(id<UITableViewDelegate>)delegate { if (delegate != self) { _trueDelegate = delegate; } else { [super setDelegate:self]; } } 

I then redefine them to handle message forwarding

 -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature *sig; sig = [[self.delegate class] instanceMethodSignatureForSelector:aSelector]; if (sig == nil) { sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; } return sig; } - (void)forwardInvocation:(NSInvocation *)anInvocation { SEL selector = anInvocation.selector; if ([self respondsToSelector:selector]) { [anInvocation invokeWithTarget:self]; } else { [anInvocation invokeWithTarget:_trueDelegate]; } } 

The problem is that unrealized delegate methods are never called in the table view, so they are not given the opportunity to be redirected to the _trueDelegate object.

I tried checking them out here:

 - (BOOL)respondsToSelector:(SEL)aSelector { } 

but this method is never called for UITableViewDelegate methods, although it is well versed in other methods.

+6
source share
1 answer

For performance, the UITableView checks and remembers which delegation methods are available as soon as the delegate is installed. First you set the delegate to self , then trueDelegate . Therefore, at the moment the delegate is set to a UITableView , trueDelegate is nil , and therefore -respondsToSelector: this always returns NO .

To fix this, set the delegate after trueDelegate . In addition, you can simplify the forwarding code. Delete all the code you specified above, except for the property, and replace it with:

 - (void)setDelegate:(id <UITableViewDelegate>)delegate { if (delegate == self) return; self.trueDelegate = delegate; [super setDelegate:self]; } - (BOOL)respondsToSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector]) return YES; return [self.trueDelegate respondsToSelector:aSelector]; } - (id)forwardingTargetForSelector:(SEL)aSelector { return self.trueDelegate; } 
+12
source

Source: https://habr.com/ru/post/920461/


All Articles