1

我有一个视图控制器,它定义了一个本身继承另一个协议的协议。我希望任何实现我的协议的对象也实现继承的协议。

我想将我的班级设置为拦截继承协议中的一些消息,以便在内部配置一些东西,但最终想将所有消息转发给我班级的代表

我可以编写很多样板代码来存根所有协议并实习生调用委托,但我发现它经常中断 - 任何时候“超级”协议发生变化,我都需要再次重新存根这个类。

我看到这在自定义 UI 控件中非常重要。重用现有组件时 - 例如表或集合视图,您希望数据源响应所有常见协议,但在某些情况下,您需要根据索引配置视图或保存特定状态。

我已经尝试使用forwardingTargetForSelector来转发我不回复的消息,但它并不总是转发......

这是一个人为的代码示例:

Class A: (the top most protocol)

@

    protocol classAProtocol <NSObject>

    -(void)method1;
    -(void)method2;
    -(void)method3;

    @end

    My Class

    @protocol MyClassProtocol <classAProtocol>

    -(void)method4;
    @end

    @interface MyClass

    @property (nonatomic,weak> id <MyClassProtocol> delegate;

    @end

    @interface MyClass (privateInterface)

    @property (nonatomic,strong) ClassA *classAObject;
    @end
    @implementation MyClass

    -(init)
    {
      self = [super init];
      if (self)
      {
        _classAObject = [[ClassA alloc] init];
        _classAObject.delegate = self; // want to answer some of the delegate methods but not all
      }
    }

-(void)method1
{
  // do some internal configuration
  // call my delegate with
  [self.delegate method1];
}
    -(id)forwardingTargetForSelector:(SEL)aSelector
    {
        if ([self respondsToSelector:aSelector])
        {
            return self;
        }
        if ([self.delegate respondsToSelector:aSelector])
        {
            return self.delegate;
        }
        return nil;
    }

    -(void)setDelegate:(id <MyClassProtocol>)delegate
    {
      self.delegate = delegate; // will forward some of the messages
    }
    @end
4

2 回答 2

3

从 self 返回forwardingTargetForSelector:没有意义,因为如果 self 响应选择器,它将永远不会被调用。

你需要实现这三个方法:

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([self.delegate respondsToSelector:[anInvocation selector]])
        [anInvocation invokeWithTarget:self.delegate];
    else
        [super forwardInvocation:anInvocation];
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    return [super respondsToSelector:aSelector] || [self.delegate respondsToSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
    NSMethodSignature *signature = [super methodSignatureForSelector:selector];
    if (!signature) {
        signature = [self.delegate methodSignatureForSelector:selector];
    }
    return signature;
}
于 2013-08-21T12:24:45.433 回答
0

你永远不应该return self;forwardingTargetForSelector:. 您的检查应该意味着它永远不会,但如果您确实返回self它会导致无限循环。

您需要确保超类没有实现该方法,因为这将阻止forwardingTargetForSelector:被调用。检查是否实际调用了该方法。

forwardingTargetForSelector:也仅当在控制器上调用它不响应的方法时才调用。在您的示例中,您没有调用[self ...];,您正在调用[self.delegate ...];,因此forwardingTargetForSelector:不会被调用。

于 2013-08-21T12:10:32.853 回答