好朋友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秒一次。
有人知道我能做到吗?
答案 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
挂钩到按钮操作并观察循环:
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)
}
}
}