UITableView и presentViewController отображает 2 клика для отображения

Я использую UITableView для представления множества viewControllers. В зависимости от того, какой индекс щелкнут, он представит другой контроллер представлений, который затем может быть отклонен. По какой-то причине один из моих ViewControllers отображает два клика. Таким образом, кажется, что каждый другой клик работает. Другие презентации презентаций работают нормально, поэтому таблица, вероятно, хорошо.

То, что я вижу в представлении ViewController, которое должно отображаться, заключается в том, что при первом щелчке он выполняет его через didSelectRowAtIndexPath, а затем запускается в целевом представлении: ViewWillLoad, ViewLoaded, ViewWillAppear.... но не ViewDidAppear. Во втором щелчке будет отображаться только ViewDidAppear. Во втором клике он даже не проходит через didSelectRowAtIndexPath. Кроме того, я могу щелкнуть в любом месте экрана во второй раз, и он отобразится.

Он будет продолжать делать это взад и вперед, по-видимому, только отображая целевой вид каждый другой клик. Любые мысли, почему это происходит?

/* RightPanelViewController */
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch(indexPath.row){
    case 0:
        // this view takes two clicks to display
        [self presentViewController:self.delegateRef.savedRidesViewController animated:YES completion:nil];
        break;
    case 1:
        // this works fine, as do others
        [self presentViewController:self.delegateRef.sensorsViewController animated:YES completion:nil];
        break;
    case 2:
       ...
}

/* savedRidesViewController */
- (void) viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated{
   [super viewDidAppear:animated];
}

Ответ 1

Проверьте это: https://devforums.apple.com/thread/201431 Если вы не хотите читать все это - решение для некоторых людей (включая меня) должно было сделать вызов presentViewController явно в основном потоке:

dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:myVC animated:YES completion:nil];
});

Вероятно, iOS7 запутывает потоки в didSelectRowAtIndexPath.

Ответ 2

После гораздо большей отладки я смог определить, что это не контроллер представления, а что-то делать с didSelectRowAtIndexPath и presentViewController. Это начало происходить с другими взглядами, которые я представлял, и не надежно. Я также попытался использовать if/else вместо переключателя без помощи.

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

Он не так чист от кода, но теперь он надежно работает. Мне все еще интересно, зачем это нужно.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
    switch(indexPath.row){
        case 0:
            [self performSelector:@selector(load0:) withObject:nil afterDelay:0];
            break;
        case 1:
            [self performSelector:@selector(load1:) withObject:nil afterDelay:0];
            break;
        case 2:
            [self performSelector:@selector(load2:) withObject:nil afterDelay:0];
            break;
        ...
    }
}

-(void)load0:(id)sender {
     [self presentViewController:self.delegateRef.zonesViewController animated:YES completion:nil];
}
-(void)load1:(id)sender {
     [self presentViewController:self.delegateRef.sensorsViewController animated:YES completion:nil];
}
-(void)load2:(id)sender {
     [self presentViewController:self.delegateRef.savedRidesViewController animated:YES completion:nil];
}

Ответ 3

Это фактическая ошибка в presentViewController:animated:completion:. См. Мой ответ с надлежащим обходным пути здесь: fooobar.com/questions/76538/...

Ответ 4

Swift 3:

DispatchQueue.main.async(execute: {
   self.present(yourViewControllerHere, animated: true, completion: nil)
})

Ответ 5

В Swift и iOS9 это:

dispatch_async(dispatch_get_main_queue(), {
    self.performSegueWithIdentifier("OpenBookingDetail", sender: self)
})

Ответ 6

Одной из причин такого поведения может быть то, что ваш код представления таблиц и, следовательно, код для запуска ваших других контроллеров представлений не выполняется в основном потоке. Но весь код, связанный с пользовательским интерфейсом, должен быть выполнен в основном потоке для правильной работы.
Таким образом, убедитесь, что код работает в основном потоке, например. путем установки соответствующей точки останова.

Ответ 7

Как уже упоминалось, одно исправление заключается в том, чтобы явно выполнить любое представление контроллеров представления в основном потоке или использовать performSelector.

Однако мне было непонятно, почему это было исправление, потому что у меня создалось впечатление, что didSelectRow работает в основном потоке. Только после того, как я прочитал этот ответ, мне стало ясно.

Подробнее см. связанный ответ, но, как представляется, это влияет на ячейки, у которых есть стиль выделения none. Это отключает анимацию (по умолчанию серого), которая возникает, когда ячейка выбрана, что означает, что цикл запуска не запускается, когда вызывается didSelectRow. Поэтому, когда вы переходите к представлению другого контроллера представлений, анимация, которая на самом деле представляет его, сразу не возникает в цикле выполнения.

Решение простого запуска его на основном потоке не является прямым исправлением. Вам просто нужно запустить цикл выполнения, например, предоставив ему некоторый код, и он будет работать. Например:

dispatch_async(dispatch_get_main_queue(), {}) [self presentViewController:viewController animated:YES completion:nil]

также исправит его. Это имеет побочный эффект запуска цикла выполнения при представлении контроллера представления, так что анимация контроллера вида теперь происходит мгновенно. Вот почему работает вызов performSelector.

Ответ 8

В конце метода didSelectRow отмените его выбор, чтобы он был доступен для выбора в следующий раз.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 .
 .
 .
 tableView.deselectRow(at: indexPath, animated: false)
}