如何在一系列子视图中添加手势识别器?

时间:2012-04-21 12:57:46

标签: objective-c ios uiviewcontroller uigesturerecognizer

我有一个显示在屏幕上的子视图图像;它基本上是一系列以棋盘格式排列在屏幕上的图像。我只想在每个图像子视图中添加手势识别器,以便当用户触摸其中一个图像子视图时,我可以检索子视图,即坐标,标签等。我的视图层次结构如下:

  1. 超级视图
  2. gridContainer视图
  3. 和每个子视图 - 带图片
  4. 在查看Apple文档之后,似乎我应该能够将一个手势识别器添加到gridContainer视图中,并且每个子视图(带有图像)都应该继承手势识别器。到目前为止,这是我尝试过的:我已经在getter中分配了初始化网格容器视图。此外,在getter中我调用了createGesture方法,该方法应该将一个手势识别器添加到gridContainer视图中。但是我在运行时遇到一个错误,指向我的动作handleSingleTap方法。它读取EXC_BAD_EXCESS。 值得注意的是,我不希望gridContainer视图之外的视图响应任何触摸事件。提前感谢您的帮助。

    以下是我正在尝试实施的代码:

    - (UIView *)gridContainerView
    {
        if (!_gridContainerView)_gridContainerView = [[UIView alloc] init];
        [self createGesture];
        return _gridContainerView;
    }
    - (void)createGesture
    {
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
                                             initWithTarget:self.gridContainerView
                                             action:@selector(handleSingleTap:)];
        singleTap.numberOfTapsRequired = 1;
    
        [self.gridContainerView addGestureRecognizer:singleTap];
    }
    

    如果您需要查看任何其他有用的代码,请告知我们。

    编辑:包括handleSingleTap方法:

    - (IBAction)handleSingleTap:(id)sender
    {
        CGPoint tapPoint = [sender locationInView:sender];
        NSLog(@"sender = %@",sender);
        NSLog(@"tappoint = %@", tapPoint);
    }
    

3 个答案:

答案 0 :(得分:4)

您正在为gridContainerView初始化普通UIView。然后您将手势识别器附加到它(使用该视图实例作为目标)。然而,普通的UIView没有实现handleSingleTap:,因此您会得到例外。

您应该创建一个(自定义UIView派生的)类来实现您需要触发该手势的选择器。

答案 1 :(得分:0)

马上出现了几个问题(甚至没有处理你的手势)。

每次访问gridContainerView时,您都将调用createGesture。您可能只希望在创建视图时发生这种情况。另外,如果你看一下createGesture,它会回调到gridContainerView,它会回调到createGesture,它会调回gridContainerView等。

你可能想要更像......的东西。

- (UIView *)gridContainerView
{
    if (!_gridContainerView) {
        _gridContainerView = [[UIView alloc] init];
        [self createGesture];
    }
    return _gridContainerView;
}

接下来,您尝试在视图上调用handleSingleTap。你可能想在控制器上使用它:initWithTarget:self。

- (void)createGesture
{
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
                                         initWithTarget:self
                                         action:@selector(handleSingleTap:)];
    singleTap.numberOfTapsRequired = 1;

    [self.gridContainerView addGestureRecognizer:singleTap];
}

您可能希望重新考虑使用两种直接相互引用的独立方法的智慧。但是,至少我们对访问者所做的更改应该没问题。要知道,如果在访问器中添加更多代码,则必须在调用createGesture之前完全设置视图。

答案 2 :(得分:0)

一些事情。首先,您将gridContainerView实例化为标准UIView,然后向其发送消息:handleSingleTap:,它肯定不会响应。如果您希望gridContainerView响应消息,则需要子类化UIView,创建适当的方法,并将gridContainerView实例化为子类。

其次,对于整体方法,我将为gridContainerView创建子类(甚至可以称之为)并创建处理手势的方法。在该方法中,您可以使用UIGestureRecognizer方法locationInView:访问触摸/点击的点。使用此点确定轻触gridContainerView中的哪个子视图并执行相应的操作。要查找已点击的子视图,您可以遍历子视图并检查每个子视图以确定哪个子视图包含被点击的点。 UIView有几种方法可以用来做到这一点:

pointInside:withEvent: hitTest:withEvent:

注意,您可以为活动传递nil。以上两件事情略有不同。如果您只是测试该点是否位于视图中,请使用pointInside:withEvent,因为它将返回BOOL。方法hitTest:withEvent将使视图搜索其所有子视图并返回其自身或其子视图之一(如果该点位于其边界之外,则返回nil)。 hitTest:withEvent可能会更加耗费处理器。此外,您也可以使用CGRectContainsPoint()进行测试。