意外的表重新加载/刷新有一些延迟

时间:2014-09-05 12:10:12

标签: uitableview core-data swift ios8

Xcode 6 - beta 6/7:我创建了一个iOS 8(Swift)博客阅读器应用程序,其中包含概述(表格视图)和详细视图(Web视图)屏幕。如果有互联网连接,应用程序在启动时会从博客中加载实际的json数据,并将其作为实体对象保存到核心数据中。首先显示的表视图然后用核心数据中的那些对象填充其单元格。包含标题和副标题的单元格像预期的那样完全加载。一切似乎都很好但是......

  1. 如果我没有互动并且只是等待,表格视图会在大约10秒后快速刷新(单元格变为空白并在半秒内再次填充相同的文本)。之后一切正常,我可以点击指定的单元格并转发到详细视图,我可以返回并选择任何其他。

  2. 如果我立即开始交互,就像通常那样,我必须在转发到详细视图之前单击一次单元格。当我在很短的时间内回到概览时,我发现我的桌面视图只填充了我之前刚拍过的一个单元格,剩下的就是空白。

  3. Case where I go back within no time and then go for one of the blank cells

    • 要么我可以等待另一个5-15秒再自动刷新(从那时起工作正常)或
    • 我可以点击那些立即再次可见的空白单元格,而 - 当然 - 我会再次转发到详细视图或
    • 如果我在详细视图上站了很长时间,让我们说阅读一些博客,然后返回,所有单元格都可见,因为有足够的时间在此期间发生这种奇怪的刷新

    • 作为备注:如果没有互联网连接,应用程序会成功加载核心数据中的对象,但提到的问题仍然存在。所以,无论如何,我必须等到应用程序运行之前发生“第二次刷新”,就像我想要的那样。

    如果这是一个完全未知的问题,你必须看到一些代码供进一步调查,我很乐意分享它。但是现在我还没有看到一点,因为它或多或少是使用表视图时实现的基本代码。我对核心数据相当新,可能已经监督了一些但到目前为止没有被注意到的东西。 我非常感谢你提供一些帮助,因为我通常会在询问之前花很长时间调查,但这次真的不知道原因是什么。

    修改

    可能很重要的是,我在Xcode中使用“Master-Detail Application”模板启动了应用程序,并使用它提供的方法来自动填充来自核心数据(NSFetchedResultsController)的正确实体对象的单元格。代码的某些部分可以提示进一步调查的地方(请告诉我,如果需要更多代码):

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        self.configureCell(cell, atIndexPath: indexPath)
        return cell 
    }    
    
    func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
        let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject
        cell.textLabel?.text = object.valueForKey("title")?.description
        let published = object.valueForKey("published")?.description
        let author = object.valueForKey("author")?.description
        let spaceholder = "   "
        cell.detailTextLabel?.text = published! + spaceholder + author!
    }
    

    编辑2:

    感谢输入nzeltzer我认为我已经找到了重点:当代码的某些部分在全局(而不是主)线程上运行时,上面的问题出现只是。所以我做了一些测试:当应用程序为第一次构建时,底部的控制台输出显示NSThread.isMainThread()结果。

    当我重新运行应用第二次以及更多时,过程如下:核心数据已经有一些值,因此直接配置了单元格(Log:_ is Main Thread)。然后,如果有互联网连接,它将删除(在viewDidLoad中)所有核心数据对象,再次加载json数据,将对象放入核心数据并再次创建单元格。现在,Log的第二部分再次_ is NOT Main Thread。如果我现在在没有互联网连接的情况下运行应用程序,则第二部分不会被触发,只会发生_ is Main Thread的第一个单元格配置。

    对这种行为有任何直接的解释吗?

    在任何情况下,派遣那些可能导致主线程问题的部分的正确(优雅)方法是什么?它是否与模板的内置NSFetchedResultsController有关,或者是否正常将某些任务自动分派到全局队列?

    记录(第一次的应用构建,10个单元格):

    2014-09-08 13:04:54.821 Blog Reader[3682:193346] 17545849:_UIScreenEdgePanRecognizerEdgeSettings.edgeRegionSize=13.000000
    2014-09-08 13:04:54.823 Blog Reader[3682:193346] 17545849:_UIScreenEdgePanRecognizerEdgeSettings.edgeRegionSize=13.000000
    NumbersOfRowsInSection is Main Thread
    NumbersOfRowsInSection is Main Thread
    
    NumbersOfRowsInSection is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    configureCell is NOT Main Thread
    cellForRowAtIndexPath is NOT Main Thread
    

2 个答案:

答案 0 :(得分:1)

我有类似的问题。
您需要在主线程上进行任何ui更改。当您执行数据请求时,回调可能不在主线程上。所以要做到这样的事情:

dispatch_async(dispatch_get_main_queue()){    
    self.tableView.reloadData() // reload table/data or whatever here. However you want.
}

当你从一个url加载数据时,你将会有一些回调,它将被发送到一个闭包(objc中的一个块)。当调用该闭包时,不保证在主线程上。有时它可能会,有时它不会。为什么要运行dispatch_async并告诉它使用dispatch_get_main_queue()获取主线程,请在主线程上运行以下代码。必须从主线程进行所有UI更改。

答案 1 :(得分:0)

您也可以像这样重新加载UITableView

self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)

As I mentioned here