好的,我有点困惑。
我有一个UIScrollView的子类,这是我尝试像UI元素一样横向滚动“表格视图”。 UIScrollView本身设置它在内部使用的UIGestureRecognizers,它似乎将自己设置为那些UIGestureRecognizers的委托。我在我的水平表元素/单元格上也有自己的UIGestureRecognizer设置,我自己的类设置为我自己的UIGestureRecognizer的委托。由于我的类是UIScrollView的子类,在运行时,UIGcureRecognizer委托调用来到我的类,用于UIScrollView内置的UIGestureRecognizers和我自己的UIGestureRecognizers。有点像PITA,但我们可以通过传递我们不关心的那些来解决这个问题。
-(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] - [MyAppHorizontalImageScroller gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]:无法识别的选择器发送到实例0x21dd50
我原以为它应该显示
- [UIScrollView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]
但这可能没问题。但问题在于它表示它会做出响应,然后却没有。
另外两个UIGestureRecognizer委托例程使用此代码(显然是不同的选择器)。
感谢您的任何见解。
答案 0 :(得分:23)
除非你覆盖对类中的选择器的响应,否则在调用super时将使用默认实现,这将检查当前实例。如果要查看某种对象的实例是否响应选择器,请使用+(BOOL)instancesRespondToSelector:(SEL)aSelector;
这将检查对象及其父对象。因此,在您的情况下,您需要以下内容:
[UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]
答案 1 :(得分:17)
[super respondsToSelector:@selector(frobnosticate:)]
没有按你的想法行事。
它转到超类,在那里获得respondsToSelector:
的实现,然后在当前对象上运行它。换句话说,super
表示与self
相同的对象,它只是在继承树中将方法查找提高了一步。
所以你在这个子类上运行respondsToSelector:
,它回复“是”,但后来试图从超类中获取gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
,而超类没有它。
要检查直接超类的实例,您可以使用instancesRespondToSelector:
,如jjburka推荐的那样,但我建议使用[self superclass]
作为主题,如下所示:
[[self superclass] instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)];
避免硬编码类名。
答案 2 :(得分:5)
在查看其他答案后,最佳解决方案是使用[[MapControllerSublcass1 superclass] instancesRespondToSelector:_cmd]
。如果您使用上面推荐的内容(例如[BaseClass instancesRespondToSelector:_cmd]
),则会遇到更改类层次结构的问题,并且意外忘记将BaseClass
更改为新的超类或子类。
[[self superclass] instancesRespondToSelector:...]
不正确,正如上面评论中所解释的那样,Apple's documentation (See respondsToSelector: in NSObjct)实际上是这样说的。它仅在您具有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];
}
}
答案 3 :(得分:0)
致电时
[super respondsToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]
这将转到超类并运行其respondsToSelector
的实现。这将查看实例(在本例中为自定义滚动视图),并确定它是否响应该选择器。
致电时
[super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
您尝试使用该方法的超类实现发送消息,在这种情况下不存在,从而导致崩溃。
看起来jjburka首先得到它 - 你需要打电话
[UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]
此外,如果您使用来自无法识别的选择器的-[super performSelector:]
,它也不会崩溃 - 执行选择器获取选择器的实例实现。它会因无限递归而崩溃。
答案 4 :(得分:0)
作为具有相同案例的人的摘要,原始问题中存在两个问题:
instancesRespondToSelector:
。把它放在一起就可以了:
// … In subclass implementation file
@interface UIScrollView () <UIGestureRecognizerDelegate> @end
// … In gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
if ([UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) {
return [super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
}