Правильный способ реализации TouchesMoved?

У меня есть настраиваемый UIView, который генерирует набор вложенных представлений и отображает их в строках и столбцах, как плитки. Я пытаюсь разрешить пользователю касаться экрана, и по мере движения пальца плитки под ним исчезают.

Приведенный ниже код - это настраиваемый 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];
}

Этот подход работает, но если плитки становятся более плотными (т.е. маленькие плитки и больше плиток на экране). IPhone менее отзывчив на движение пальца. Это может быть хит-тест, который сказывается на процессоре, поскольку он изо всех сил пытается успевать, но хотелось бы получить некоторые мнения.

Мои вопросы:

  1. Это эффективный / правильный способ реализовать touchMoved?

  2. Если нет, то какой подход рекомендуется?

  3. Я попытался переместить функциональность в пользовательский класс Tile (подчиненный UIView), который класс выше создаст и добавит в качестве подчиненного представления. Этот элемент подвида Tile может обрабатывать TouchesBegan, но по мере движения пальца другие плитки не получают TouchesBegan, даже если прикосновения все еще являются частью начальной последовательности касаний. Есть ли способ реализовать это через класс Tile subview, как другие плитки получают событие TouchesBegan / TouchesMoved при перемещении пальца?


person Ronnie Liew    schedule 18.10.2008    source источник


Ответы (3)


  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. Вам нужно более четко решить, что должно происходить у вашего родителя и что должно происходить в каждой плитке. Вы упомянули выше, что хотите, чтобы плитки получали события touchesBegan, но вы не добавили для этого никакого кода. Когда вы это представили, вам, вероятно, следует подумать об использовании слоев вместо представлений (если вы не выполняете какую-либо обработку событий, связанных с плиткой). Все, что у вас есть, можно сделать с помощью отслеживания событий в родительском элементе. Имейте в виду, что если у вас СЛИШКОМ много представлений (или слоев), это будет медленно. Мы пробовали использовать сетку 15x15 в кроссвордах, и, хотя для некоторых вещей это было нормально, в конце концов мы отказались от подхода сетки слоев.

(Не уверен, почему нумерация здесь возобновилась с 1 ...)

person Ben Gottlieb    schedule 18.10.2008
comment
Спасибо за отзыв по этому поводу. Если бы мне пришлось перенести обработку событий на настраиваемое подвид Tile, как бы базовые плитки уведомлялись, когда палец перемещается по ним? Касания по-прежнему будут «принадлежать» первоначальной последовательности касаний для первой плитки. - person Ronnie Liew; 19.10.2008
comment
Как описано выше, все касания обрабатываются родительским представлением. Я обычно нахожу это проще, чем пытаться отразить прикосновения от брата или сестры к брату. Вам придется поэкспериментировать с сообщениями touchMoved, чтобы точно узнать, как они будут вести себя при изменении целевого представления. - person Ben Gottlieb; 19.10.2008

одно дополнение, вместо проверки попадания вы можете просто проверить, находится ли точка в CGRect, который представляет фрейм каждого подпредставления. У меня есть похожее приложение, и оно сработало лучше всего для меня.

for (UIView* aSubview in self.subviews) {

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

       //Do stuff
    }
}
person Corey Floyd    schedule 23.01.2009

Просто идея, которая может помочь ... Я не тестировал это, но после обнаружения касания на конкретном просмотре изображения отключите userInteractionEnabled для всех других просмотров изображений ...

Я полагаю, это поможет немного увеличить скорость, поскольку iPhone не хватит ресурсов, пытаясь определить, какое изображение нажимается во время перетаскивания. То же самое и с мультитачем.

person Duck    schedule 30.12.2008