Reputation: 2819
I want to forwarding all UITableViewDelegate method to another object for some reason 。 Here is the code I wrote , but because there are so many methods in UITableViewDelegate.I have to write to many if else compare for each method.
- (id)forwardingTargetForSelector:(SEL)aSelector
{
NSString* selector = NSStringFromSelector(aSelector);
if ([selector isEqualToString:@"tableView:didSelectRowAtIndexPath:"])
{
return self.outDelegate;
}
else
{
return [super forwardingTargetForSelector:aSelector];
}
}
And I think there is a better solution to do this.can I do it like below,how to test aSelector is Defined in aProtocol or not
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if (**aSelector is Defined in aProtocol**)
{
return self.outDelegate;
}
else
{
return [super forwardingTargetForSelector:aSelector];
}
}
Upvotes: 2
Views: 543
Reputation: 30791
In UIKit, Apple do this in UIUserNotificationRestrictedAlertViewProxy's respondsToSelector to check isAlertViewDelegateMethod but I have modified the code to work with the UITableViewDelegate so here you go:
BOOL isTableViewDelegateMethod(SEL selector) {
struct objc_method_description desc;
desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, NO, YES);
if(desc.name){
return YES;
}
desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, YES, YES);
if(desc.name){
return YES;
}
return NO;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if (isTableViewDelegateMethod(aSelector))
{
return self.outDelegate;
}
else
{
return [super forwardingTargetForSelector:aSelector];
}
}
And you may want to also check UITableViewDataSource since table views have two delegates.
Upvotes: 0
Reputation: 4457
You can get a C array of the methods in a protocol using protocol_copyMethodDescriptionList
:
int numOfMethods;
struct objc_method_description * method_description_list;
method_description_list = protocol_copyMethodDescriptionList(@protocol(protocolName),
YES, YES, &numOfMethods)
The number of descriptions in the array is now stored in the numOfMethods
variable. You can then iterate through this array and check whether the selector for each method is equal to the current selector using ==
rather than converting the selectors to strings:
for (int i=0; i<numOfMethods; i++) {
if (aSelector == method_description_list[i].name)
//forward to other delegate
else
return [super forwardingTargetForSelector:aSelector];
}
Note that you will need to do free(method_description_list)
to reclaim the memory it occupies once you are done with it.
There is no point in recreating and freeing it every time forwardingTargetForSelector:
is called, so you might want to do something like turning it into an iVar and creating it in init
, and then free
ing it in dealloc
, since the protocol is very unlikely to change over the lifetime of this object
Upvotes: 2
Reputation: 932
When you want perform this kind of forwardInvocation and delegate method validation you can use "respondToSelector" and "conformsToProtocol" methods and do the respective ForwardInvocation process.
Upvotes: 0
Reputation: 5967
You can use respondsToSelector:
to check if a delegate has the selector
Also, you could use conformsToProtocol:
in combination with respondsToSelector: as -
if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @selector(aMethod)])
{
//send message;
}
Upvotes: 1
Reputation: 1169
Check like this -
if([delegate conformsToProtocol:@protocol(yourProtocolName)])
{
//Do Something
}
Upvotes: 0