在原始子类中捕获委托方法调用

Posted

技术标签:

【中文标题】在原始子类中捕获委托方法调用【英文标题】:Catching a delegate method call in the originating subclass 【发布时间】:2014-03-06 18:26:58 【问题描述】:

我可以尝试用 UIScrollView 来解释这一点

我将创建一个 UIScrollView 的子类。我希望能够响应它自己的委托方法,例如 scrollViewDidScroll 但同时让委托正常设置。我怎样才能不干扰委托属性,但仍然让子类能够响应自己的委托调用?

【问题讨论】:

您可以为您的自定义 UIScrollView 添加第二个委托,这会触发它自己的方法。 @Larme 感谢您的意见,但这并不是我要问的,如果我不清楚,请见谅。我希望委托类能够实现 UIScrollViewDelegate 必须提供的所有委托方法。但我只想“监听”一些选定的委托方法,我不想必须在子类中实现每个委托方法,这样我就可以将它们前言给它自己的委托。 How to subclass UIScrollView and make the delegate property private的可能重复 【参考方案1】:

如果你只关心scrollViewDidScroll,只需覆盖layoutSubviews

- (void)layoutSubviews 
    [super layoutSubviews];

    // your code here

UIScrollView 在将 scrollViewDidScroll: 发送给其代表之前,先发送自己 layoutSubviews

【讨论】:

甜!!,我没想到。这实际上适用于我需要的 scrollViewDidScroll,谢谢。但它实际上并没有回答这个问题,所以我认为我不应该将它标记为答案。对不起【参考方案2】:

这需要一些时间,但你可以实现你想要的。

//已编辑

我添加了方法forwardInvocation: 的实现。当对象无法识别发送给它的消息时,在对象上调用此方法。

在我们的例子中,当 UIScrollView 委托的一些方法将被调用并且我们的子类并没有实现被调用的方法时,forwardInvocation 将被调用。这个方法检查被调用的选择器是否是UIScrollViewDelegate 协议的一部分。如果是,并且如果我们类的“true”委托响应此选择器,我们会将调用的选择器的调用转发给我们的自定义委托。

话虽如此,使用此解决方案您不必在子类中实现UIScrollViewDelegate 协议的所有方法。不会在ScrollView 的子类中实现的方法的执行将被转发给我们子类的“真正”委托。

例子:

#import <objc/runtime.h>

@protocol YourSubclassDelegate<UIScrollViewDelegate>
@end

 @interface YourSubclass ()
    @property (nonatomic, weak) id<YourSubclassDelegate> delegate;
 @end


@implementation 

//override delegate setter
- (void)setDelegate:(UIScrollViewDelegate)delegate

  self.customDelegate = delegate;
 [super setDelegate:self];
 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

   //do something you want
   if ([self.customDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) 
      [self.customDelegate scrollViewDidScroll:self];
   



- (id)forwardingTargetForSelector:(SEL)selector

   struct objc_method_description methodDescription = protocol_getMethodDescription(@protocol(UIScrollViewDelegate), selector, YES, YES);

   if(NULL != methodDescription.name) 
      if ([self.customDelegate respondsToSelector:selector]) 
        return self.customDelegate;
      
   

   return nil;
 



@end

【讨论】:

这种方法很好,但是您可以通过使用扩展 UIScrollViewDelegate 协议的新协议来节省对选择器工作的响应。 customDelegate 将符合这个新协议,并且只有在对象符合新协议时才会在 setDelegate 中设置。 是的,这是我的解决方案,我很高兴其他人也想到了它。但我在想一定有更好的方法。 我已经更新了我的答案。完成您想要的结果所需的代码更少。

以上是关于在原始子类中捕获委托方法调用的主要内容,如果未能解决你的问题,请参考以下文章

从 UITextField 子类捕获委托方法而不是委托

从另一个类调用委托方法

未调用 MKMapViewDelegate 子类方法

CALayer委托方法drawLayer没有被调用

子 ViewController 不调用父类中声明的委托方法

子类可以使用超类Ios的委托方法吗