TableView上的更新无效

时间:2016-02-16 19:42:40

标签: ios uitableview tableviewcell

好朋友StackOverflow。

我的应用程序上有一个聊天屏幕,我根据数组的实际大小执行插入和删除。看这个:

func addObject(object: Object?) {

    if comments == nil || object == nil || object?.something == nil || object?.anything == nil {
      return
    }

    self.objectsTableView.beginUpdates()

    if self.objects!.count == 10 {
      self.objects?.removeAtIndex(9)
      self.objectsTableView.deleteRowsAtIndexPaths([NSIndexPath(forRow : 9, inSection: 0)], withRowAnimation: .Right)
    }

    self.objects?.insert(object!, atIndex: 0)
    self.objectsTableView.insertRowsAtIndexPaths([NSIndexPath(forRow : 0, inSection: 0)], withRowAnimation: .Right)

    self.objectsTableView.endUpdates()

  }

但经过一些压力测试后,日志会通知:

  

无效更新:第0部分中的行数无效   更新(1)后必须包含在现有部分中的行   等于之前该部分中包含的行数   更新(10),加上或减去插入或删除的行数   该部分(1个插入,0个删除)和加号或减号的数量   移入或移出该部分的行(0移入,0移出)。

我不知道发生了什么,只有当物体的插入非常极端时才会发生这种情况,例如每0.2秒一次。

有人知道我能做到吗?

2 个答案:

答案 0 :(得分:1)

型号不匹配

  

更新(1)后现有部分中包含的行数必须等于更新前的该部分中包含的行数(10),加上或减去从该部分插入或删除的行数(1个插入,0个删除)

对于合理的人,用简单的英语,10认为你应该有11行:
更新前加{+ 1}} 1

  

更新后的现有部分中包含的行数(1)

...指的是numberOfRowsInSection正在为1部分返回0,这表示objects数组不同步,假设您使用如下内容:

override func tableView(tableView: UITableView,
                        numberOfRowsInSection section: Int) -> Int {
    return objects.count
}

使用NSFetchedResultsController

一个干净的解决方案是使用NSFetchedResultsController作为模型和UI之间的接口。它已经很好地研究了样板代码,是确保线程安全的绝佳平台。 here

注意:

效果很好!细胞似乎旋转到顶部 我无法使用您生成的Documentation here来破解它,也无法安排多个并发测试。您的Object数组必须有恶意访问

<强>演示

此简化版本有效。只需将doPlusAction挂钩到按钮操作并观察循环:

Gist

class TableViewController: UITableViewController {
    var objects:[Int] = [0,1,2,3,4]
    var insertions = 5

    @IBAction func doPlusAction(sender: AnyObject) {
        tableView.beginUpdates()

        objects.removeAtIndex(4)
        tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 4, inSection: 0)], withRowAnimation: .Right)
        objects.insert(insertions++, atIndex: 0)
        tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Right)
        tableView.endUpdates()

        let delay = 0.1 * Double(NSEC_PER_SEC) //happens the same with this too, when reach 100-150 items
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
        dispatch_after(time, dispatch_get_main_queue()) { () -> Void in
            self.doPlusAction(self)
        }
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objects.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
        cell.textLabel!.text = "Cell \(objects[indexPath.row])"
        return cell
    }
}

答案 1 :(得分:0)

解决问题的人的名字:信号量

错误仍然存​​在,但仅限于列表中的大项目。我不知道会发生什么。

DataSource协议:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let count = self.objects?.count ?? 0
    if self.semaphore != nil && semaphoreCode == BLOCKED_STATE {
      dispatch_semaphore_signal(self.semaphore!)
    }
    return count
  }

添加对象的方法:

func addObject(object: Object?) {

    if object == nil {
      return
    }

    if self.semaphore != nil {
      let tempSemaCode = dispatch_semaphore_wait(semaphore!, 100000)
      if tempSemaCode == BLOCKED_STATE {
        self.semaphoreCode = RELEASED_STATE
      }
    }

    if self.objects != nil && semaphoreCode != BLOCKED_STATE {

      var needsRemoveLastItem = false
      if self.objects!.count == 10 {
        self.objects?.removeAtIndex(9)
        needsRemoveLastItem = true
      }
      self.objects?.insert(object!, atIndex: 0)

      if self.objects!.count > 0 {
        self.objectsTableView.beginUpdates()
        if needsRemoveLastItem {
          self.objectsTableView.deleteRowsAtIndexPaths([NSIndexPath(forRow : 9, inSection: 0)], withRowAnimation: .Right)
        }
        self.objectsTableView.insertRowsAtIndexPaths([NSIndexPath(forRow : 0, inSection: 0)], withRowAnimation: .Right)
        self.objectsTableView.endUpdates()
        self.semaphore = dispatch_semaphore_create(BLOCKED_STATE)
      }

    }

  }