iOS segue 在显示新视图之前冻结数秒



在我的应用程序的主视图中,我有一个表格视图和两个原型单元格。我已经使用故事板为每个单元格配置了 segue。在视图控制器中,我覆盖 prepareForSegue 以将所选单元格上的信息传递到目标视图。

目标视图不是特别复杂,当然不需要任何繁重的处理来加载。

问题所在

当我第一次点击主控制器中的单元格时,目标视图会在长时间延迟后出现,从 5 秒到 40 秒。

编辑#2:后续点击通常更快

请注意:

    如果我在目标视图出现
  • 之前再次点击同一单元格,这将触发目标视图立即出现。
  • 如上所述,但点击不同的单元格会导致视图立即出现,但包含第一个单元格中的数据。
  • 如上所述,但点击其他控件(没有关联的 segue)会触发目标视图立即显示。
  • 随后的"点击"通常表现出较少的延迟。
  • 时间剖析器 - 据我所知 - 显示在那几秒钟的延迟中绝对没有发生任何事情。
  • 我尝试了不同类型的 segue,但没有区别
  • 一些 println 显示发生了以下事件序列:

    • 在主视图中,准备Segue被执行(没有延迟)
    • 然后执行目标视图DidLoad(无延迟)
    • 。耽误时间长...
    • 目标控制器中的集合视图和表视图开始调用数据源相关方法,以从控制器提取数据。
    • 视图终于出现(带有不需要的动画,顺便说一句,但这是一个不同的问题)

从我读到的有关此主题的内容来看,我怀疑该问题可能与后台线程中发生的上述某些操作有关。

知道我可能做错了什么吗?

编辑#1:添加了一些代码

在主视图控制器中,已使用故事板链接 segue(按住 CTRL 将两个原型单元格拖动到目标视图中)。

代码看起来有点像下面:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    var assetIndex = assetsTable.indexPathForSelectedRow()?.row
    println("prepare for segue - start: (assets[assetIds[assetIndex!]]!.Name)")
    if let destination = segue.destinationViewController as? AssetThingsListViewController
    {
        destination.bundlesRepository = bundlesRepository!
        destination.asset = assets[assetIds[assetIndex!]]
    }
    println("prepare for segue - end")
}

编辑#3我已经在BitBucket上提供了一个示例项目

我检查了你的项目。虽然我也找不到其他任何东西,但我也怀疑这是线程的问题。

我设法通过为tableview实现委托并在代码中呈现新控制器来解决问题:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let destination = storyboard?.instantiateViewControllerWithIdentifier("BuilderToysListViewController") as! BuilderToysListViewController
    destination.botsRepository = botsRepository!
    destination.builder = builders[builderIds[indexPath.row]]
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.presentViewController(destination, animated: true) { () -> Void in
        }
    })
}

请注意,您设置了视图控制器情节提要 id:BuilderToysListViewController,还设置了表视图委托。不要忘记删除 segue。

最后,要在新的视图控制器中解散视图,请使用以下代码:

@IBAction func backButton(sender: AnyObject)
{
    dismissViewControllerAnimated(true, completion: { () -> Void in
    })
//        performSegueWithIdentifier("segueToysByBuilder", sender: nil)        
}

这将允许您正确关闭视图,而不是错误地创建新视图。

很难

说,除非您发布的代码响应单元格上的点击并呈现新的视图控制器。

UI 更改

长时间延迟(或 UI 更改从未发生)的一个常见原因是尝试从后台线程进行 UI 更改。调用 segue 的代码是否有可能在不同的线程上运行?您可以通过在该代码上设置断点并在中断时观察线程编号来轻松判断这一点。如果线程编号为 0,则表示正在主线程上运行。如果是其他线程编号,那就是您的问题。

如果有任何代码,也值得将代码从 viewWillSeem 移动到 viewDidAppear

我能够通过实现以下内容来使用 Swift 13 为 iOS 5 解决此问题:

DispatchQueue.main.async {
     self.performSegue(withIdentifier: "YOURSEGUEID", sender: nil)
}

内部

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}

最终结果

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    DispatchQueue.main.async {
         self.performSegue(withIdentifier: "YOURSEGUEID", sender: nil)
    }
}

最新更新