0

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

  1. 超级视图
  2. 一个 gridContainer 视图
  3. 和每个单独的子视图 - 带有图像

在查看了苹果文档之后,似乎我应该能够向 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);
}
4

3 回答 3

4

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

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

于 2012-04-21T13:08:40.447 回答
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 之前完全设置视图。

于 2012-04-21T13:25:56.857 回答
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()测试。

于 2012-04-21T13:26:04.657 回答