延迟呈现模态视图控制器

时间:2014-10-20 15:25:20

标签: ios objective-c iphone modalviewcontroller

我有一个基于标签栏的应用。所有5个选项卡中都有导航控制器,自定义视图控制器实例正确设置为根视图控制器。加载就好了。其中一些视图控制器包含表视图。我想在用户在表视图中选择一行时向用户显示模态视图控制器。 didSelectRowAtIndexPath委托方法的(相关部分)如下所示:

SampleSelectorViewController *sampleVC = [[SampleSelectorViewController alloc] init];
[self presentViewController:sampleVC animated:YES completion:NULL];

模态视图控制器出现但是在非常明显的延迟之后出现。有时它甚至要求用户第二次点击该行。我已经验证过的一些事情是:

  • 当用户点击行时调用表视图的didSelectRowAtIndexPath方法
  • didSelectRowAtIndexPath方法不包含任何阻止调用。没有执行网络操作,模态视图控制器的设置不涉及任何处理密集型任务。它显示的数据是静态的。
  • 如果我将新视图控制器推到导航堆栈上(其他所有内容保持完全相同),它的行为完全没有任何延迟。只有在以模态方式呈现时才会遇到延迟。

有任何想法/建议吗?

10 个答案:

答案 0 :(得分:54)

似乎在presentViewController:animated:completion内调用tableView:didSelectRowAtIndexPath:是有问题的。在仪器中使用Time Profiler时也很难找到任何突出的东西。有时我的模态视图会在不到一秒的时间内出现,有时需要4s甚至9s。

我认为这与基础UIPresentationController和布局有关,这是我在选择时间区域和选择时间分析器中的模态演示之间选择时间区域时所看到的少数几项内容之一。

雷达存在描述此问题:http://openradar.appspot.com/19563577

解决方法很简单但不满意:稍微延迟演示文稿以避免引起减速的任何引起争议的行为。

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

答案 1 :(得分:3)

您应该从根vc以模态方式显示它(例如:customTabBarRootViewController)。 保存参考,并使用参考控制器显示它。

答案 2 :(得分:3)

我猜您也将单元格的selectionStyle设置为UITableViewCellSelectionStyleNone。我更改为UITableViewCellSelectionStyleDefault,它可以正常工作。

答案 3 :(得分:2)

tableView:didSelectRowAtIndexPath:呈现看起来像是一个Apple bug时,我也有这种奇怪的延迟。

这个解决方案似乎运作良好。

CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Fixes a bug where the main thread may be asleep, especially when using UITableViewCellSelectionStyleNone

答案 4 :(得分:2)

斯威夫特4:     你可以使用如下。

DispatchQueue.main.async {
            let popUpVc = Utilities.viewController(name: "TwoBtnPopUpViewController", onStoryboard: "Login") as? TwoBtnPopUpViewController
            self.present(popUpVc!, animated: true, completion: nil)
        }

它对我有用。

答案 5 :(得分:2)

如果在tableView(:didSelectRowAt :)中调用present(:animated:completion :),selectionStyle == .none对于选定的tableview单元格,则您有这种奇怪的行为,然后尝试调用在tableView(_:didSelectRowAt :)中进行任何操作之前,先进行tableView.deselectRow(at:animated:)。

对您有帮助吗?

答案 6 :(得分:1)

Swift 3

中的解决方案

在SampleSelectorViewController(呈现的视图控制器)中使用以下代码

Public Class Form1
    Dim txtbx As New TextBox
    Dim pctbx As New PictureBox
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        txtbx.Dock = DockStyle.Top
        pctbx.Dock = DockStyle.Bottom
        pctbx.BackColor = Color.AntiqueWhite
        pctbx.AllowDrop = True
        Controls.Add(txtbx)
        Controls.Add(pctbx)
        AddHandler pctbx.DragEnter, AddressOf pctbx_DragEnter
        AddHandler pctbx.DragDrop, AddressOf pctbx_DragDrop

    End Sub

    Private Sub pctbx_DragEnter(sender As Object, e As DragEventArgs)
        e.Effect = DragDropEffects.All
    End Sub

    Private Sub pctbx_DragDrop(sender As Object, e As DragEventArgs)
        txtbx.Text = "select from employees where id = "
    End Sub



End Class

答案 7 :(得分:1)

此行为的常见问题如下:

为tableView中的单元格设置selectionStyle = .none(似乎不像http://openradar.appspot.com/19563577所写的那样依赖UITableViewController子类)并在委托方法中使用

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

动画取消选择

tableView.deselectRow(at: indexPath, animated: true)

表示非动画单元的动画。

在这种情况下,随后的视图控制器演示会有延迟。

有一些解决方法,包括在主线程上使用dispatch_async,但最好不要在代码中无法选择的单元格上没有动画的情况下调用deselectRow

答案 8 :(得分:0)

根据@ Y.Bonafons的评论,在Swift中,您可以这样尝试(对于Swift 4.x和5.0)

DispatchQueue.main.async {

                self.showAction() //Show what you need to present
            }

答案 9 :(得分:0)

试试这个 对于 swift 5.2 版,您可以使用以下代码:

DispatchQueue.main.async(execute:{self.present(nav, animated: true)})