Objective c 如何将手势识别器添加到一系列子视图中?

Objective c 如何将手势识别器添加到一系列子视图中?,objective-c,ios,uiviewcontroller,uigesturerecognizer,Objective C,Ios,Uiviewcontroller,Uigesturerecognizer,我有一个显示在屏幕上的子视图图像网格;它基本上是以棋盘格的方式在屏幕上排列的一系列图像。我只想在每个图像子视图中添加手势识别器,以便当用户触摸其中一个图像子视图时,我可以检索子视图,即坐标、标记等。我的视图层次结构如下所示: 超级视野 gridContainer视图 和每个单独的子视图-带有图像 在看过苹果的文档之后,我似乎应该能够在gridContainer视图中添加一个手势识别器,并且每个子视图(带有图像)都应该继承手势识别器。到目前为止,这就是我所尝试的:我已经在getter中初始化了网格

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

  • 超级视野
  • gridContainer视图
  • 和每个单独的子视图-带有图像
  • 在看过苹果的文档之后,我似乎应该能够在gridContainer视图中添加一个手势识别器,并且每个子视图(带有图像)都应该继承手势识别器。到目前为止,这就是我所尝试的:我已经在getter中初始化了网格容器视图。此外,在getter中,我调用了我的create手势方法,该方法应该向gridContainer视图添加手势识别器。但是,我在运行时遇到一个错误,它指向我的action handleSingleTap方法。上面写着EXC_BAD_过剩。 还值得注意的是,我不希望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);
    }
    

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


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

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


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

    一下子就出现了几个问题(甚至没有处理手势)

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

    你可能想要更像

    - (UIView *)gridContainerView
    {
        if (!_gridContainerView) {
            _gridContainerView = [[UIView alloc] init];
            [self createGesture];
        }
        return _gridContainerView;
    }
    
    接下来,您将尝试调用视图上的handleSingleTap。您可能希望它位于controller:initWithTarget:self上

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

    您可能想重复使用两个单独的方法的智慧,它们可以像这样直接相互引用。但是,至少在我们对访问器进行了更改之后,应该是可以的。只需知道,如果在访问器中添加更多代码,则在调用CreateSpirate之前,必须完全设置视图。

    立即出现几个问题(甚至没有处理手势)

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

    你可能想要更像

    - (UIView *)gridContainerView
    {
        if (!_gridContainerView) {
            _gridContainerView = [[UIView alloc] init];
            [self createGesture];
        }
        return _gridContainerView;
    }
    
    接下来,您将尝试调用视图上的handleSingleTap。您可能希望它位于controller:initWithTarget:self上

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

    您可能想重复使用两个单独的方法的智慧,它们可以像这样直接相互引用。但是,至少在我们对访问器进行了更改之后,应该是可以的。只需知道,如果在访问器中添加更多代码,则在调用CreateSpirture之前必须完全设置视图。

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

    第二,作为一种整体方法,我将为gridContainerView创建子类(甚至可以这样称呼它),并创建处理手势的方法。在该方法中,您可以使用UIgestureRecognitor方法
    locationInView:
    访问触摸/点击的点。使用此点确定gridContainerView中的哪个子视图被点击,并执行适当的操作。要发现哪个子视图被点击,您可以迭代子视图并检查每个子视图以确定哪个子视图包含被点击的点。UIView有几种方法可用于执行此操作:

    pointInside:withEvent:
    hitTest:withEvent:


    注意,您可以为事件传递
    nil
    。以上两件事的作用略有不同。如果只是测试该点是否位于视图中,请使用
    pointInside:withEvent
    ,因为它将返回
    BOOL
    。方法
    hitTest:withEvent
    将导致视图搜索其所有子视图,并返回其自身或其中一个子视图(如果点超出其边界,则返回nil)<代码>hitTest:withEvent可以稍微占用处理器。此外,您也可以使用
    CGRectContainsPoint()
    进行测试

    几件事。首先,将gridContainerView实例化为标准UIView,然后向其发送消息:handleSingleTap:,它肯定不会响应该消息。如果你想要你的gridCon