超级respondsToSelector:返回true,但实际上调用超(选择)给出“无法识别的选择发

2019-06-27 15:57发布

OK,我有点困惑。

我的UIScrollView的子类,这是我在一个水平滚动的“表视图”像UI元素的尝试。 UIScrollView的本身设置UIGestureRecognizers内部使用,它似乎将自己设置为代表的那些UIGestureRecognizers。 我也有我的水平表格元素/电池我自己UIGestureRecognizer设置和我自己的类集合为委托我自己UIGestureRecognizer。 由于我的类的UIScrollView的子类,在运行时,UIGestureRecognizer委托调用来我班的两个UIScrollView的内置UIGestureRecognizers和我自己的UIGestureRecognizers。 皮塔饼的一点,但我们可以通过传递上,我们不关心的那些解决这个问题。

-(BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
   if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]])
      return NO; 
      else
      {  
        if ([super respondsToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)])
           return [super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
           else 
           return NO;
        }
}

问题是,检查[super respondsToSelector:@selector()]返回YES,但是当我后来居然把它return [super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; 我得到下面的异常

2012-08-31 12:02:06.156 MyApp的[35875:707] - [MyAppHorizo​​ntalImageScroller gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]:无法识别的选择发送到实例0x21dd50

我本来以为它应该显示

- [UIScrollView中gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]

但是,这可能是确定。 但问题是,它说,它响应,然后没有。

另外两个UIGestureRecognizer委托程序与此代码的工作(不同的选择很明显)。

感谢您的任何见解。

Answer 1:

除非你重写响应在你的类选择器您将使用默认的实现,当你调用super将检查当前实例。 如果你想看看一个对象类型的实例响应选择使用+(BOOL)instancesRespondToSelector:(SEL)aSelector;

这将检查的对象和它的父对象。 所以你的情况,你想以下几点:

[UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]


Answer 2:

[super respondsToSelector:@selector(frobnosticate:)]不会做你的想法。

它去超,得到实施respondsToSelector:在那里,然后运行它的当前对象 。 换句话说, super代表同一对象self ,它只是开始的方法查找在继承树高一个台阶。

所以,你正在运行respondsToSelector:在这个子类,其中回答“是”,但后来试图让gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:从超,不拥有它。

要检查的直接超类的实例,你可以使用instancesRespondToSelector:作为jjburka建议,但我会建议[self superclass]作为受试者,就像这样:

[[self superclass] instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)];

这避免了硬编码的类名称。



Answer 3:

看着其他的答案后,最好的解决办法是使用[[MapControllerSublcass1 superclass] instancesRespondToSelector:_cmd] 如果您使用的是上面推荐的,像[BaseClass instancesRespondToSelector:_cmd]你碰上改变你的类层次结构,不慎忘记改变的问题BaseClass新的超类或子类。

[[self superclass] instancesRespondToSelector:...]如上的评论解释,它实际上是这么说的上是不正确苹果的文档(:在NSObjct见respondsToSelector) 。 只有当你拥有1级子类的作品,所以它给你的错觉 ,这是一个实际的解决方案。 我爱上了它。

[[super class] instancesRespondToSelector:...]不起作用,会这样问题的关键所在。

例如,我有一个BaseMapController实现一些在方法MKMapViewDelegate ,但它没有实现mapView:regionWillChangeAnimated: MapControllerSublcass1从继承BaseMapController 。 而MapControllerSubclass2从继承MapControllerSublcass1

在我的代码,我有这样的事情,并能正常工作。

MapControllerSublcass1.m:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
  if ([[MapControllerSublcass1 superclass] instancesRespondToSelector:_cmd]) {
    [super mapView:mapView regionWillChangeAnimated:animated];
  }
}

MapControllerSubclass2.m:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
  if ([[MapControllerSubclass2 superclass] instancesRespondToSelector:_cmd]) {
    [super mapView:mapView regionWillChangeAnimated:animated];
  }
}


Answer 4:

你打电话的时候

[super respondsToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]

这是要超和运行其实现respondsToSelector 。 这看起来的情况下(在这种情况下,您的自定义滚动视图),并确定它是否响应该选择与否。

你打电话的时候

[super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];

您尝试使用超类实现该方法,在这种情况下不存在发​​送消息,导致崩溃。

貌似jjburka得首先 - 你需要调用

[UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]

另外,如果你使用它不会崩溃-[super performSelector:]从无法识别的选择-执行选择得到落实情况的选择的。 它会崩溃的无限递归。



Answer 5:

至于有人用同一案件的总结,也有原来的问题两个问题:

  1. 检查是否超响应该选择,这是建议的@jjburka最好使用完成instancesRespondToSelector:
  2. 其实调用的是超类的方法,无需编译器抱怨,即使它在一个私人的标头的声明。 这可以通过在一个类别重新声明它整齐地实现(见这个问题 )。

将其组合在一起这给:

// … In subclass implementation file
@interface UIScrollView () <UIGestureRecognizerDelegate> @end

// … In gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
if ([UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) {
    return [super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
}


文章来源: super respondsToSelector: returns true but actually calling super (selector) gives “unrecognized selector sent to instance”