Rod*_*Rod 24 iphone uitableview
我有一个应用程序,其中UITableView的数据源每隔30秒由一个后台线程从远程服务器更新.
如果用户正在滚动tableView或者正在进行tableView,则会发生崩溃reloadTableView:.崩溃的原因是崩溃时表中的行数与重绘开始时的行数不匹配.
当请求的TableView单元格超出范围时会发生另一次崩溃,因为在numberofTableViewCells:调用时间和调用时间之间cellfForRowAtIndexPath,数据模型已更改且单元格不再存在.
tableView的数据从后台线程更新.在从服务器加载数据时,用户仍应能够与tableView进行交互,但现在导致崩溃.
在更新tableViewDataSource时,如何阻止tableView滚动或重新加载?这种情况的最佳做法是什么?
谢谢.
Tec*_*Zen 18
简短的回答是,您需要缓冲数据模型中的数据,并且仅在未滚动表时使用新数据更新表.这需要在数据模型中完成,因为数据源委托不知道数据模型中的内容或更改的内容.
然而,从UI设计的角度来看,在用户滚动时主动更新表将使用户迷失方向.用户会认为他们位于桌子的顶部/中部/底部,然后突然发现自己位于底部/顶部/中部.用户会认为他们已经查看了表格的一个部分中的所有数据,但实际上该表格将添加他们需要查看的内容.例如,如果表是按字母顺序排列的名称列表,则用户检查所有以"U"开头的名称,看到没有名称,然后检查表中的其他位置.同时,当用户在其他地方寻找时,该表以新名称无形地更新"U"部分.即使用户理解表是动态更新的(大多数都不是),他们也必须不断滚动检查几乎整个表,看看有什么变化.
更好的UI设计是为用户提供更新的能力.在栏中放置"更新"或"新数据可用"按钮,然后将其设置为在新数据到达时显示.单击按钮后,冻结表,更新,然后让用户恢复交互.在视觉上标记添加的行也是一个很好的设计.
这将使用户更容易理解用户界面,同时解决崩溃问题.
如果您不使用Core Data,则为了实现表的实时和不可见更新.你需要冻结调用– tableView:numberOfRowsInSection或– numberOfSectionsInTableView:之前– tableView:cellForRowAtIndexPath:调用.
由于– tableView:numberOfRowsInSection首先调用,我会在那里调用第一次更新,然后冻结您的数据模型.这样,数据模型将返回适当数量的节和行.
我认为你必须将数据模型划分为两个部分,其中一个部分将缓冲输入数据,另一个部分将命令数据显示.您的更新方法应将所有已完成的缓冲数据移动到显示数据部分.
此外,您可能需要为用户何时不移动表设置计时器.如果没有主动操作表,则计时器应调用update方法,然后应强制更新.
如果您使用Core Data,您可以使用NSFetchedResultController 它的委托方法将在数据模型更改时通知您.它应该返回正确更新的正确部分和行信息.以这种方式驱动更新表非常容易.但是,它不能很快克服数据进入模型的问题,以至于模型在方法调用之间发生变化.您仍然需要冻结和/或减慢模型.但是,你不需要计时器.
核心数据是您最好的选择,但即使如此,它也很难实现,因为您正在尝试针对UI的内容做一些事情,因此API不会轻易支持它.
回顾这个答案,我看到我忽略了[UITableView beginUpdates]在添加或删除行时会冻结表的配置.它与[UITableView endUpdates]包含UI中的更改配对.
从后台线程调用GUI对象(如UITableView)上的方法是不安全的.
你需要做一些事情:
[ tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]
Run Code Online (Sandbox Code Playgroud)
请参阅uitableview-drawing-problems-when-reloaddata-is-called
| 归档时间: |
|
| 查看次数: |
9046 次 |
| 最近记录: |