TableView reloadData() 不显示所有数据,即使带有值的数组已填充(swift)
Posted
技术标签:
【中文标题】TableView reloadData() 不显示所有数据,即使带有值的数组已填充(swift)【英文标题】:TableView reloadData() not showing all data, even though the array with values is filled (swift) 【发布时间】:2015-02-12 13:11:07 【问题描述】:我有一个表格视图,其中填充了 http 调用的结果。数据被传递到名为tripTimes
的数组中。 triptimes
包含有关特定日期的某些旅行的信息。当天每趟行程的开始时间传入self.tableData
,并插入到tableView中。
在此之后,我重新加载表格并...奇怪的结果。
数组tableData
被正确填充,但在我调用self.tableView.reloadData()
之后,几乎所有单元格都被正确填充。但是,第一个单元格是空的,直到我点击它或者我等待大约 5 秒并且最后一个单元格也是空的,但它在同一时间后获得与第一个单元格相同的值。
我认为它与 dispatch_async
部分有关,但我对 swift 和 ios 还很陌生,所以我不知道去哪里找。当我在dispatch_async
函数中打印self.tableData
的内容时,数组包含正确的值。
下面是我的viewController的代码
import UIKit
import Foundation
import SwiftHTTP
class TripSelect: UIViewController, UITableViewDataSource, UITableViewDelegate
@IBOutlet weak var dateTextField: UITextField!
@IBOutlet weak var tableView: UITableView!
@IBAction func showTrips(sender: AnyObject)
//if data is already present in tableData, empty it first
if self.tripTimes.count != 0 && self.tableData.count != 0
for var i=0; i<self.tripTimes.count; i++
self.tableData.removeObjectAtIndex(0)
let indexPathToRemove = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.deleteRowsAtIndexPaths([indexPathToRemove], withRowAnimation: .Automatic)
dispatch_async(dispatch_get_main_queue(),
self.tableView.reloadData()
)
var request = HTTPTask()
request.GET("<MY_URL>", parameters: ["date": dateTextField.text], success: (response: HTTPResponse) in
if let data = response.responseObject as? NSData
let str = NSString(data: data, encoding: NSUTF8StringEncoding) as String
let str2 = "\"not enough data for this day\""
if str != str2
let json:AnyObject = JSON.parse(str)
self.dayLatLongs = json["dayLatLongs"] as Array
self.tripTimes = json["tripTimes"] as Array
var tripLatLongs:[AnyObject] = self.dayLatLongs[0] as Array
var firstTrip:[AnyObject] = tripLatLongs[0] as Array
var tripStartTime:String = ""
for var i=0; i<self.tripTimes.count; i++
tripStartTime = self.tripTimes[i]["startTime"] as String
//println("\(tripStartTime)")
self.tableData.addObject(tripStartTime)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
dispatch_async(dispatch_get_main_queue(),
println(self.tableData)
self.tableView.reloadData()
)
else println(str)
,failure: (error: NSError, response: HTTPResponse?) in
println("error: \(error)")
)
var dayLatLongs:[AnyObject] = []
var tripTimes:[AnyObject] = []
var tableData: NSMutableArray! = NSMutableArray()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.tableData.count
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.tableData.objectAtIndex(indexPath.row) as? String
return cell
override func viewDidLoad()
super.viewDidLoad()
var backgroundView = UIView(frame: CGRectZero)
self.tableView.tableFooterView = backgroundView
self.tableView.backgroundColor = UIColor.clearColor()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
更新:
var indexPaths:[NSIndexPath] = [NSIndexPath]()
for var i=0; i<self.tripTimes.count; i++
tripStartTime = self.tripTimes[i]["startTime"] as String
self.tableData.addObject(tripStartTime)
indexPaths.append(NSIndexPath(forRow: i, inSection: 0))
self.tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .Automatic)
现在结果显示正确,但只有在我“拖动”表格几次之后。
【问题讨论】:
success
块很可能在主线程上运行,因为 showTrips
似乎在主线程上被调用。无需在insertRowsAtIndexPaths
和deleteRowsAtIndexPaths
之后使用reloadData
,但您需要确保使用正确的索引插入和删除单元格,并且仅在主线程上:尝试使用所有索引填充数组并进行一次插入/删除调用以简化该过程。
好的,我尝试了其他方法(更新了我的问题),所以现在可以正确显示这些值,但只有在我“拖动”表格几次之后。
尝试对删除方法执行相同的操作,至于线程:您似乎确保只有对 reloadData
的调用在主线程上,对插入/删除调用执行相同的操作:从这个意义上说,它们与reloadData
非常相似,应该始终在主线程上调用。在这种情况下,reloadData
调用可能会被删除,因为表格会自动更新,您可能会弄乱动画。
非常感谢!这解决了问题:) 动画现在也正常显示了,非常好!我会发布一个答案,这样更容易找到
【参考方案1】:
您的问题出在第一个 if 子句中:
if self.tripTimes.count != 0 && self.tableData.count != 0
for var i=0; i<self.tripTimes.count; i++
self.tableData.removeObjectAtIndex(0)
let indexPathToRemove = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.deleteRowsAtIndexPaths([indexPathToRemove], withRowAnimation: .Automatic)
dispatch_async(dispatch_get_main_queue(),
self.tableView.reloadData()
)
您总是只删除索引0
处的值,而不使用i
。所以用你的索引i
替换所有硬编码的0
:
if self.tripTimes.count != 0 && self.tableData.count != 0
for var i=0; i<self.tripTimes.count; i++
self.tableData.removeObjectAtIndex(i)
let indexPathToRemove = NSIndexPath(forRow: i, inSection: 0)
self.tableView.deleteRowsAtIndexPaths([indexPathToRemove], withRowAnimation: .Automatic)
dispatch_async(dispatch_get_main_queue(),
self.tableView.reloadData()
)
【讨论】:
感谢您的快速回答,尽管这不是问题。当我第一次填表时,程序不会执行那部分代码,因为self.tripTimes.count
和self.tableData.count
在那个时候都是0(我用println检查过)【参考方案2】:
这个答案的所有功劳归于@A-Live。
更新了建议的更改:
要删除单元格,我将函数更改为
dispatch_async(dispatch_get_main_queue(),
if self.tripTimes.count != 0 && self.tableData.count != 0
self.tableData = []
self.tableView.deleteRowsAtIndexPaths(self.indexPaths, withRowAnimation: .Automatic)
self.indexPaths = []
)
要添加单元格,我将函数更改为
dispatch_async(dispatch_get_main_queue(),
for var i=0; i<self.tripTimes.count; i++
tripStartTime = self.tripTimes[i]["startTime"] as String
self.tableData.addObject(tripStartTime)
self.indexPaths.append(NSIndexPath(forRow: i, inSection: 0))
self.tableView.insertRowsAtIndexPaths(self.indexPaths, withRowAnimation: .Automatic)
)
【讨论】:
很高兴它起作用了,最后一点:确保您在同一个线程上修改数据源,以使所有更新操作线程安全。在这种情况下,将循环和tableData = []
移动到您已经拥有的 GCD 块内。否则,对showTrips
的后续调用可能会尝试在(可能)不同的分离线程上修改相同的数组(通常是数据源)。以上是关于TableView reloadData() 不显示所有数据,即使带有值的数组已填充(swift)的主要内容,如果未能解决你的问题,请参考以下文章
使用通知中心和 tableview.reloaddata() 不刷新表视图
tableView.reloadData() 如何正确重新加载数据?