UITableView和presentViewController需要2次点击才能显示

Mir*_*iro 30 objective-c uitableview ios

我使用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];
}
Run Code Online (Sandbox Code Playgroud)

AXE*_*AXE 56

看看这个:https://devforums.apple.com/thread/201431 如果你不想全部阅读 - 一些人(包括我)的解决方案是presentViewController在主线程上显式调用:

dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:myVC animated:YES completion:nil];
});
Run Code Online (Sandbox Code Playgroud)

可能iOS7正在弄乱线程didSelectRowAtIndexPath.

  • 这样做的原因是某些东西(可能是表视图)在didSelect之后在主线程上做了一些工作...被调用,它以某种方式取消了视图控制器的表示.异步调用主队列允许运行循环完成(以及表视图完成它正在做的事情)然后我们可以呈现视图控制器.这是一个臭混乱. (2认同)
  • 在 iOS 11 上仍然如此。我同意这不是线程本身的问题,而是时间问题。`DispatchQueue.main.async { }` 将在下一个 runloop 开始一个任务,从而允许 tableView 首先完成它的事情。 (2认同)

Mir*_*iro 6

经过更多的调试,我能够确定它不是视图控制器,而是与didSelectRowAtIndexPath和presentViewController有关.它开始发生在我所呈现的其他观点上,而且不可靠.我也试过使用if/else代替switch而没有帮助.

最终我发现这个解决方案能够解决它,但我不完全确定原因.通过无延迟地使用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];
}
Run Code Online (Sandbox Code Playgroud)


Tam*_*ola 5

这是中的实际错误presentViewController:animated:completion:。在此处查看我的答案以及适当的解决方法:https : //stackoverflow.com/a/30787046/1812788


Phi*_*hil 5

斯威夫特3:

DispatchQueue.main.async(execute: {
   self.present(yourViewControllerHere, animated: true, completion: nil)
})
Run Code Online (Sandbox Code Playgroud)