我有UITableView
名为itemDisplayTable
。其中的每个单元格都有倒数计时器和文本字段。我希望只要值发生变化,就可以使用服务器中的数据更新文本字段。所以我每秒使用NSTimer
重新加载整个表视图。
override func viewDidAppear(animated: Bool) {
var call = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("refresh"), userInfo: nil, repeats: true)
}
func refresh() {
// GET request from the server
itemDisplayTable.reloadData()
}
表格视图代码:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (tableView.tag == 1)
{
let cell = tableView.dequeueReusableCellWithIdentifier("collectionCell") as! CollectionCell
cell.category.text = categoryName1[indexPath.row]
setUpScrollView(cell.scrollView,categoryname: categoryName1[indexPath.row])
return cell
}
else
{
let cell = tableView.dequeueReusableCellWithIdentifier("categoryName") as! CategoryTableViewCell
cell.categoryImage .image = UIImage(named: categoryImage[indexPath.row])
cell.categoryName.text = itemname[indexPath.row]
return cell
}
}
func setUpScrollView(scroll : UIScrollView ,categoryname:NSString ){
scroll.subviews.map{ $0.removeFromSuperview() }
items = self.retriveStatus(categoryname as String)
for item in items {
let array = NSBundle.mainBundle().loadNibNamed("collectionView", owner: self, options: nil) as NSArray
let view = array.objectAtIndex(0) as! ItemDisplayView
view.frame = CGRectMake(CGFloat(190 * items.indexOf(item)!)+20, 0, 170 , 250)
view.layer.borderColor=UIColor(red: 231.0/255, green: 231.0/255, blue: 231.0/255, alpha: 1).CGColor
view.layer.borderWidth = 1.0
if item.offerstatus == "active" {
view.invalidateTimer()
view.showOfferTime(item.itemExpiryDate!)
}
view.currentBidPrice.text = item.currentBidPrice // my text field data
scroll.addSubview(view)
}
scroll.contentSize = CGSize(width: (190 * items.count)+20, height: 250)
}
}
tableView的Cell元素的类:
class ItemDisplayView: UIView {
@IBOutlet weak var currentBidPrice: UILabel!
@IBOutlet var timerLabel: UILabel!
func showOfferTime(dString:NSString) -> Void {
offerTimer = NSTimer.scheduledTimerWithTimeInterval(1, target:
self, selector: #selector(self.converDatetoTime(_:)),
userInfo:dString, repeats: true)
}
func invalidateTimer() -> Void {
offerTimer.invalidate()
}
func converDatetoTime(timer:NSTimer) -> Void {
let dString = timer.userInfo
let dateAsString = dString
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy, HH:mm:ss"
let date = dateFormatter.dateFromString(dateAsString as! String)
timerLabel.text = self.stringFromTimeInterval(date!.timeIntervalSinceDate(NSDate())) as String
}
func stringFromTimeInterval(interval:NSTimeInterval) -> NSString {
let ti = NSInteger(interval)
//let ms = Int((interval % 1) * 1000)
let seconds = ti % 60
let minutes = (ti / 60) % 60
let hours = (ti / 3600)
if interval>0 {
return NSString(format: "%0.2d:%0.2d:%0.2d",hours,minutes,seconds)
} else {
return "00:00:00"
}
}
问题:文本字段正在完美更新,但由于tableView每秒都会重新加载,倒数计时器似乎是" 00:00:00"虽然它正在积极运行。
有没有办法在单元格内单独更新或重新加载文本字段,或者避免倒数计时器显示" 00:00:00"。
答案 0 :(得分:1)
重新加载整个tableView不是这样做的方法;它很慢,特别是如果你有一张大桌子。有没有办法可以打开套接字来监听服务器的更改,只更新服务器发送更改时更改的特定单元格?您可以使用以下命令重新加载特定单元格,其中indexPathsArray
是指向需要刷新的任何单元格的NSIndexPaths数组:
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths(indexPathsArray, withRowAnimation: UITableViewRowAnimation.None)
tableView.endUpdates()
我建议为您的UITableView维护一个数据模型。现在,听起来您的数据状态只保存在tableView的单元格中。因此,当您每秒刷新tableView时,您将丢弃数据的当前状态。
您需要在tableView外部保留一组数据。使用结构将所有数据与单个单元格保持在一起是有帮助的,这样您就不必维护多个数据数组。也许你会有类似的东西:
struct CategoryElement {
var name: String // category's name
var imageName: String // category's image name
var timer: NSTimer // the current timer for that cell item
var value: String // the text field value ?
}
(您可能希望保留更多/更少的数据,但我不能100%确定您在问题中做了什么。)
然后你的视图控制器将有一个dataModel数组,其中包含所有tableView单元格的所有信息:var dataModel: [CategoryElement]
。
现在,在func tableView:cellForRowAtIndexPath
中,您将使用数据模型中的信息创建单元格。由于计时器保存在dataModel数组中,因此您将能够获取当前时间并刷新tableView将不会重置计时器。
if (tableView.tag == 1)
{
let cell = tableView.dequeueReusableCellWithIdentifier("collectionCell") as! CollectionCell
cell.category.text = dataModel[indexPath.row].name
setUpScrollView(cell.scrollView,categoryname: dataModel[indexPath.row].name)
return cell
}
然后在setUpScrollView:categoryname
函数中,除非项目状态发生变化,否则不应使计时器失效。相反,应该为ItemDisplayView的计时器分配dataModel[indexPath.row].timer
。无论何时需要停止或重置计时器,都必须通过dataModel[indexPath.row].timer
的数据模型进行更改。
基本上,您的func tableView:cellForRowAtIndexPath
不应更新数据模型中的任何数据。它应该只是显示它。然后,当您从服务器获得更新时,您将更新dataModel数组。要在屏幕上显示这些更改,您可以刷新整个表格(尽管如此,仅更新已更改的单元格会更有效。)
我希望这能为您提供有关如何解决问题的指导。