UISwipeGesture Не работает с использованием пользовательского UIView

Вот мой файл GameViewController.m:

- (void)viewDidLoad {
    [super viewLoad];
    .
    .
    .
    _board = [[TwinstonesBoardModel alloc] init];
    [_board setToInitialStateMain];
    TwinstonesStoneView* twinstonesBoard = [[TwinstonesStoneView alloc]
                                      initWithMainFrame:CGRectMake(12, 160, 301.5, 302.5)
                                      andBoard:_board];
    [self.view addSubview:twinstonesBoard];

    TwinstonesStonesView *stoneOne = [[TwinstonesStoneView alloc] init];
    TwinstonesStonesView *one = (TwinstonesStoneView*)stoneOne.stoneUnoView;
    TwinstonesStonesView *stoneTwo = [[TwinstonesStoneView alloc] init];
    TwinstonesStonesView *two = (TwinstonesStoneView*)stoneTwo.stoneDueView;

    UISwipeGestureRecognizer* swipeLeft = [[UISwipeGestureRecognizer alloc]
                                         initWithTarget:self
                                         action:@selector(swipeLeft:)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    swipeLeft.numberOfTouchesRequired = 1;
    [one addGestureRecognizer:swipeLeft];
    [two addGestureRecognizer:swipeLeft];

Вот соответствующий код в моем файле TwinstonesStoneView.m:

@implementation TwinstonesStoneView
{
    NSMutableArray* _array;
    NSMutableArray* _emptyArray;
    CGRect _frame;
    NSUInteger _column;
    NSUInteger _row;
    TwinstonesBoardModel* _board;

    int _i;
}

- (id)initWithMainFrame:(CGRect)frame andBoard:
                                   (TwinstonesBoardModel*)board
{
  if (Self = [super initWithFrame:frame])
  {
    float rowHeight = 49.0;
    float columnWidth = 49.0;
    float barrierHorizontalRowHeight = 12.5;
    float barrierVerticalColumnWidth = 12.5;

    for (int row = 0; row < 5; row++) 
    {
      for (int col = 0; col < 5; col++)
      {
        TwinstonesStonesView* square = [[TwinstonesStoneView alloc]
             initWithEmptyFrame:CGRectFrame(//spacial equations, not important)
             column:col
             row:row
             board:board];

        BoardCellState state = [board cellStateAtColumn:col andRow:row];

        if (state == BoardCellStateStoneOne) {
            // _stoneUnoView is a public property
            // 'stoneOneCreation' creates a UIImageView of the stone
            _stoneUnoView = [UIImageView stoneOneCreation];
            [self addSubview:square];
            [square addSubview:_stoneUnoView];
            [_array insertObject:_stoneUnoView atIndex:0];
        } else if (state == BoardCellStateStoneTwo) {
            // same idea as above
            _stoneDueView = [UIImageView stoneTwoCreation];
            [self addSubview:square];
            [square addSubview:_stoneDueView];
            [_array insertObject:_stoneDueView atIndex:1];
        } else {
            // based on the 'init' method I write below, I assumed this
            // would return an empty square cell
            [self addSubview:square];
            [_emptyArray insertObject:square atIndex:_i];
            _i++;
        }
      }
    }
    self.backgroundColor = [UIColor clearColor];
  }
  return self;
}

- (UIView*)stoneUnoView {
    return _stoneUnoView;
}

- (UIView*)stoneDueView {
    return _stoneDueView;
}

- (id)initWithEmptyFrame:(CGRect)frame
                  column:(NSUInteger)column
                     row:(NSUInteger)row
                   board:(TwinstonesBoardModel*)board
{
    self = [super initWithFrame:frame];
    return self;
}

- (void)swipeLeft:(UIGestureRecognizer*)recognizer
{
    NSLog(@"Swipe Left");
    UIView* view = recognizer.view;
    [self move:CGPointMake(-1, 0) withView:view];
}

- (void)move:(CGPoint)direction withView:view {
    // whatever code I decide to put for stone movement
}

@end

Я извиняюсь за (возможно) ненужную длину, я просто пытался понять это пару дней, и мне не повезло. Вот основные пункты того, что я пытаюсь сделать:

  1. setInititalStateMain устанавливает размещение двух камней в сетке 5x5
  2. В GameViewController.m я пытаюсь зафиксировать свойства «stoneUnoView» и «stoneDueView» (установленные в файле TwinstonesStoneView.m), дать им жесты смахивания и взаимодействовать с ними, используя методы, предусмотренные в TwinstonesStoneView.m.
  3. Я генерирую слишком много просмотров? Загвоздка в том, что все работает с точки зрения того, что я могу видеть на своем iPhone, когда запускаю программу. Камни отображаются на моем экране, но когда я пытаюсь с ними взаимодействовать, в консоли не появляется даже сообщение «NSLog».
  4. Метод 'stoneOneCreation' (и... два) принадлежат UIImageView, но, как видите, я храню их в указателе UIView.
  5. Я также использовал «[один setUserInteractionEnabled: YES]» (и ... два), но это тоже не помогло.
  6. Если я добавляю распознаватель жестов в self.view, то все работает (появляются изображения камней, игрового поля и прочей графики, а когда я взаимодействую с ЛЮБОЙ частью экрана, я вывожу указания на консоль..... .просто не конкретное взаимодействие с камнем).

Большое вам спасибо за то, что мирились со всем этим, это действительно поможет, если кто-то знает, что не так. PS: все файлы #import верны, так что это не проблема.

Я использую XCode 7, язык Objective-C и разрабатываю для iOS.

Anthony

person Anthony the Kid    schedule 30.03.2016    source источник


Ответы (2)


Вы должны добавить разные экземпляры распознавателя жестов смахивания в разные экземпляры UIView.

UISwipeGestureRecognizer* swipeLeft1 = [[UISwipeGestureRecognizer alloc]
                                     initWithTarget:self
                                     action:@selector(swipeLeft:)];
swipeLeft1.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft1.numberOfTouchesRequired = 1;
[one addGestureRecognizer:swipeLeft1];

 UISwipeGestureRecognizer* swipeLeft2 = [[UISwipeGestureRecognizer alloc]
                                     initWithTarget:self
                                     action:@selector(swipeLeft:)];
swipeLeft2.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft2.numberOfTouchesRequired = 1;
[two addGestureRecognizer:swipeLeft2];

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

person Andrew Romanov    schedule 30.03.2016
comment
До сих пор нет ответа, к сожалению. Не слишком ли много ссылок? Когда я наношу его на карту, ссылки кажутся звуковыми. Я импортировал все файлы правильно. Есть ли такая вещь, как подвиды, похороненные под подвидами? Является ли причиной того, что я не могу взаимодействовать со своими пользовательскими представлениями, потому что они каким-то образом скрыты под передней поверхностью, с которой взаимодействуют мои пальцы? - person Anthony the Kid; 30.03.2016
comment
Что вы имеете в виду только для чтения? Есть ли что-то, что я должен был бы изменить? - person Anthony the Kid; 30.03.2016
comment
Я имею в виду, что распознаватель можно привязать только к одному виду. - person Andrew Romanov; 30.03.2016
comment
И в вашем коде вы создаете _stoneUnoView и _stoneDueView в методе initWithFrame..., но в коде вы создаете экземпляры TwinstonesStonesView (stoneOne и storeTwo) с помощью метода init. Я думаю, вам нужно открыть отладчик и проверить один и два значения до нуля. - person Andrew Romanov; 30.03.2016
comment
Учитывая тот же код, который я написал в исходном сообщении, а затем применив то, что вы сказали в комментарии (два отдельных экземпляра), ответ (в частности, NSLog в методе действия) не выводится на консоль от взаимодействия с представлениями на моем айфоне. - person Anthony the Kid; 30.03.2016
comment
Я создал экземпляры TwinstonesStonesView (stoneOne и stoneTwo), чтобы получить доступ к свойствам _stoneUnoView и _stoneDueView....... иначе я бы этого не сделал. Если нет другого способа получить доступ к этим свойствам? Они оба общедоступны в файле TwinstonesStoneView.h (то есть _stoneUnoView и _stoneDueView). - person Anthony the Kid; 30.03.2016
comment
Вы используете свойства TwinstonesStoneView, созданные с помощью метода инициализации (не с помощью initWithMainFrame:..), и вы не добавляете эти экземпляры в родительское представление. Также вы используете свойства stoneUnoView и stoneDueView (из экземпляров, которые вы создаете с помощью метода init), чтобы получить представления для распознавателей, но _stoneUnoView и _stoneDueView создаются в initWithMainFrame:.. и я думаю, что в вашем коде они равны нулю. - person Andrew Romanov; 30.03.2016
comment
Это действительно отличный момент, я думаю, что это проблема. Что мне делать, чтобы это исправить? Моя логика для размышлений обо всем этом была следующей: 1) Создать экземпляры в initWithMainFrame 2) После инициализации захватить эти экземпляры со ссылками на файл TwinstonesStoneView.m 3) Использовать эти захваченные экземпляры для настройки жестов 4) Затем использовать методы смахивания назад внутри файла TwinstonesStoneView.m - person Anthony the Kid; 30.03.2016
comment
И не забудьте добавить вид камня на экран (в какой-то родительский вид). Некоторое время назад я создал небольшой проект для решения странной проблемы с неявной анимацией. Там я использую экземпляр распознавателя жестов панорамирования, но это не имеет значения, например, как управлять UIGestureRecognizer. Вы можете найти его здесь github.com/K-Be/ViewMovingTest, см. ViewController. м файл. - person Andrew Romanov; 30.03.2016
comment
Ух ты! Это действительно работает сейчас! Во-первых, я решил создать свои каменные представления в файле GameViewController.m, а затем передать их как UIViews для моей функции initWithMainFrame:. затем переместил мои методы смахивания обратно в файл GameViewController.m. - person Anthony the Kid; 30.03.2016

Привет, возможно, взаимодействие с пользователем отключено для этих представлений, жесты работают только для представлений, для которых userInteractionEnable = YES.

person Andey Satyanarayana    schedule 30.03.2016