objective-c 实现 TouchesMoved 的正确方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/215383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 20:51:24  来源:igfitidea点击:

Right way to implement TouchesMoved?

iphoneobjective-ccocoa-touch

提问by Ronnie Liew

I have a custom UIView that generates a set of subviews and display them in rows and columns like tiles. What I am trying to achieve is to allow the user to touch the screen and as the finger move, the tiles beneath it disappears.

我有一个自定义 UIView,它生成一组子视图并将它们像瓷砖一样显示在行和列中。我想要实现的是允许用户触摸屏幕,随着手指移动,它下面的瓷砖消失。

The code below is the custom UIView that contains the tiles:

下面的代码是包含图块的自定义 UIView:

- (id)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {
        int i, j;
        int maxCol = floor(self.frame.size.width/TILE_SPACING);
        int maxRow = floor(self.frame.size.height/TILE_SPACING);

        CGRect frame = CGRectMake(0, 0, TILE_WIDTH, TILE_HEIGHT);
        UIView *tile;       

        for (i = 0; i<maxCol; i++) {
            for (j = 0; j < maxRow; j++) {
                frame.origin.x =  i * (TILE_SPACING) + TILE_PADDING;
                frame.origin.y =  j * (TILE_SPACING) + TILE_PADDING;
                tile = [[UIView alloc] initWithFrame:frame];

                [self addSubview:tile];
                [tile release]; 
            }
        }

    }
    return self;
}


- (void)touchesBegan: (NSSet *)touches withEvent:(UIEvent *)event {
    UIView *tile = [self hitTest:[[touches anyObject] locationInView:self] withEvent:nil];

    if (tile != self)
        [tile setHidden:YES];
}



- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
    UIView *tile = [self hitTest:[[touches anyObject] locationInView:self] withEvent:nil];

    if (tile != self)
        [tile setHidden:YES];
}

This approach works but however if the tiles get denser (i.e. small tiles and more tiles on the screen). The iPhone is less responsive as the finger move. It may be the hitTest taking a toll on the processor as it struggles to keep up but would like some opinions.

这种方法有效,但是如果拼贴变得更密集(即屏幕上的小拼贴和更多拼贴)。手指移动时,iPhone 的响应速度较慢。可能是 hitTest 对处理器造成了影响,因为它努力跟上,但希望得到一些意见。

My questions are:

我的问题是:

  1. Is this an efficient way / right way to implement the touchesMoved?

  2. If it isn't, what would be the recommended approach?

  3. I tried moving the functionality into a custom Tile class (a sub UIView) which the class above would create and add as a subview. This subview Tile can handle the TouchesBegan but as the finger move, the other tiles does not receive the TouchesBegan even since the touches are still part of the initial touch sequence. Is there a way to implement it through the subview Tile class, how do other tiles receive the TouchesBegan/TouchesMoved event as the finger move?

  1. 这是实现touchesMoved的有效方法/正确方法吗?

  2. 如果不是,推荐的方法是什么?

  3. 我尝试将功能移动到自定义 Tile 类(子 UIView)中,上面的类将创建并添加为子视图。这个子视图 Tile 可以处理 TouchesBegan,但是随着手指的移动,即使触摸仍然是初始触摸序列的一部分,其他 Tile 也不会收到 TouchesBegan。有没有办法通过子视图Tile类来实现,其他tile是如何在手指移动时接收到TouchesBegan/TouchesMoved事件的呢?

回答by Ben Gottlieb

  1. Not really, in my experience.
  2. From the way you've set up your views, there would seem to be a much more efficient way to determine which one was tapped:
  1. 不是真的,以我的经验。
  2. 从您设置视图的方式来看,似乎有一种更有效的方法来确定哪个被点击:

 //In your init method, make sure each tile doesn't respond to clicks on its own
 ...
 tile.userInteractionEnabled = NO;
 ...


 - (void) touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
      CGPoint tappedPt = [[touches anyObject] locationInView: self];
      int     xPos = tappedPt.x / (TILE_SPACING + TILE_PADDING);
      int     yPos = tappedPt.y / (TILE_SPACING + TILE_PADDING);
      int     tilesAcross = (self.bounds.size.width / (TILE_SPACING + TILE_PADDING));
      int     index = xPos + yPos * tilesAcross;

      if (index < self.subviews.count) {
          UIView  *tappedTile = [self.subviews objectAtIndex: index];
          tappedTile.hidden = YES;
      }
  }

  1. You need to more clearly decide what should happen in your parent, and what should happen in each tile. You mentioned above that you wanted the tiles to receive touchesBegan events, but you didn't include any code for this. As you presented this, you should probably think about using layers instead of views (if you're not doing any tile-specific event handling). What you've got here can all be done with event tracking within the parent. Keep in mind that if you have TOO many views (or layers), it's gonna get slow. We tried grids of 15x15 in Crosswords, and while it was okay for some things, eventually we gave up on the grid-of-layers approach.
  1. 您需要更清楚地决定在您的父级中应该发生什么,以及在每个图块中应该发生什么。您在上面提到您希望磁贴接收 touchesBegan 事件,但您没有为此包含任何代码。正如您所提出的,您可能应该考虑使用图层而不是视图(如果您没有进行任何特定于图块的事件处理)。您在此处获得的所有内容都可以通过父级中的事件跟踪来完成。请记住,如果您有太多的视图(或层),它会变慢。我们在填字游戏中尝试了 15x15 的网格,虽然在某些情况下还可以,但最终我们放弃了网格层方法。

(Not sure why the numbering restarted with 1 here...)

(不知道为什么这里的编号从 1 重新开始......)

回答by Corey Floyd

one addition, instead of hit testing, you can just check if the point lies in the CGRect that represents the frame of each subview. I have a similar app, and this worked best for me.

另外,您可以检查点是否位于代表每个子视图的框架的 CGRect 中,而不是命中测试。我有一个类似的应用程序,这对我来说效果最好。

for (UIView* aSubview in self.subviews) {

    if([aSubview pointInside: [self convertPoint:touchPoint toView:aSubview] withEvent:event]){

       //Do stuff
    }
}

回答by DuckDucking

Just an idea that may help... I have not tested this, but, after detecting the tap on a particular imageview turn off userInteractionEnabled of the all other imageviews...

只是一个可能有帮助的想法......我没有测试过这个,但是,在检测到特定图像视图上的点击后关闭所有其他图像视图的 userInteractionEnabled ......

I suppose this will help increase a little bit the speed, as iPhone will not last resources trying to find which image is being tapped during a drag. The same is true for multitouch.

我想这将有助于提高一点速度,因为 iPhone 不会持续资源试图找到在拖动过程中被点击的图像。多点触控也是如此。