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)
}