在转发时获取ObjC方法的真实响应者

时间:2017-06-26 10:02:39

标签: objective-c proxy delegates introspection message-forwarding

我遇到了一个案例,CaptureScreenshot() / UITableView委托由代理对象(不是UICollectionView转发,只是常规对象)。

根据特定的委托方法,代理会将其转发给实际响应该方法的2个对象之一。

给定一个委托回调,我想知道响应方法调用的“真实”实例。

代理代码如下:

NSProxy

我的代码如下:

给定一个委托方法,我想知道哪个实例正在响应:

@implementation DelegateSplitter

- (instancetype)initWithFirstDelegate:(id<NSObject>)firstDelegate secondDelegate:(id<NSObject>)secondDelegate
{
    if(self = [super init])
    {
        _firstDelegate = firstDelegate;
        _secondDelegate = secondDelegate;
    }

    return self;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL aSelector = [anInvocation selector];

    if([self.firstDelegate respondsToSelector:aSelector])
    {
        [anInvocation invokeWithTarget:self.firstDelegate];
    }

    if([self.secondDelegate respondsToSelector:aSelector])
    {
        [anInvocation invokeWithTarget:self.secondDelegate];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *first = [(NSObject *)self.firstDelegate methodSignatureForSelector:aSelector];
    NSMethodSignature *second = [(NSObject *)self.secondDelegate methodSignatureForSelector:aSelector];

    if(first)
    {
        return first;
    }
    else if(second)
    {
        return second;
    }

    return nil;
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if([self.firstDelegate respondsToSelector:aSelector] || [self.secondDelegate respondsToSelector:aSelector])
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

@end

修改

当前的黑客行为(想要更全面的东西):

使模拟对象调用转发器并获取目标对象

    // delegate is an instance of DelegateSplitter
    id <UITableViewDelegate> delegate = tv.delegate; 

    SEL didSelectItemSelector = @selector(collectionView:didSelectItemAtIndexPath:);

    if ([delegate respondsToSelector:didSelectItemSelector]) {
       // the delegate splitter doesn't forward the call
       ...
       return;
    }

// the delegate (proxy) forwards the method to a different instance
    if (![delegate.class instancesRespondToSelector:didSelectItemSelector]) {
            // the delegate responds to selector but the class instances themselves do not respond to the selector. This is possible if the delegate is forwarding all invocations to a different object

               NSObject *d = (NSObject *)delegate;
         NSMethodSignature *ms = [d methodSignatureForSelector:didSelectItemSelector];

         if (ms) {

          ** I WANT TO GET THE INSTANCE WHICH IS RESPONDING**
          ????
          HOW DO I GET IT
          ?????
         }
    }

0 个答案:

没有答案