Objective-C:将大多数消息转发给另一个对象(在运行时)

时间:2014-06-19 19:06:30

标签: ios objective-c objective-c-runtime

UIView

的子类

我有MyView的子类UIView

此子类有@property UIView * realView

我想做什么

每当向MyView发送消息时,我都希望"转发消息"到self.realView,除少数消息外。

例如,在MyView的实现中,我会有这个覆盖:

- (void)setBackgroundColor:(UIColor *)color
{
     [self.realView setBackgroundColor:color] ;
}

可以在运行时自动执行,而不是明确地覆盖所有方法吗?

例外

对于某些方法,我希望有一个显式控件。例如:

- (void)setFrame:(CGRect)frame
{
    /* do stuff */

    [super setFrame:frame] ;
}

2 个答案:

答案 0 :(得分:4)

  

不是显式覆盖所有方法,而是可以在运行时自动执行吗?

您实现-forwardInvocation:方法将任何无法识别的消息发送到另一个对象。只要对象没有实现传递给它的选择器作为处理消息的第二次机会,就会调用-forwardInvocation。您可以覆盖它以将消息发送到另一个对象(这几乎是NSProxy所做的),记录消息等。

正如@cobbal在下面指出的那样,-forwardInvocation将帮助您使用超级视图中未实现的方法,但它不会处理在superview中实现 的方法,因为您的MyView继承了这些的实现。例如,如果您想使用UIView作为UIButton的代理,UIButton特有的所有方法都可由-forwardInvocation:处理,但UIView定义的方法{1}}不能。为了获得继承方法以外的行为,您当然需要覆盖。在某些情况下,您可以通过从MyViewNSObject而不是UIResponder派生UIView来解决这个问题,从而避免继承的UIView实现,但是如果{ {1}}需要成为一个真正的观点,你必须克服每一种方法。

如果你仔细想想,很难想象如果没有明确地覆盖每个继承的方法,你的目标是如何实现的。你说你只想转发大多数消息,但是糟糕的运行时如何判断你想要转发哪些消息以及你不想转发哪些消息?它所能做的就是为给定的选择器寻找一个方法,如果它找到一个方法就调用它,或者如果它没有那么就采取一些行动(比如调用MyView)。

更新: @robmayoff指出-forwardInvocation:,这对我没有发生,但在您的情况下可能是更好的解决方案。但是,它仍然无法处理您需要重定向从超类继承的方法的情况。

答案 1 :(得分:0)

完全有可能。 首先,您需要WZProtocolIntercepter。然后使用intercepter作为正常的UIView:

WZProtocolInterceptor* fakeView = [[WZProtocolInterceptor alloc]
                                  initWithInterceptedProtocol:@protocol(TheMethodsForTheMiddleManToHandle)];

fakeView.receiver = self.realView;
fakeView.middleMan = self;
[someViewController.view addSubview:fakeView];

将您想要控制的方法放在TheMethodsForTheMiddleManToHandle

@protocol TheMethodsForTheMiddleManToHandle
- (void)setFrame:(CGRect)frame;
@end