【问题标题】:Reload a table view without affecting the countdown timer in the cell重新加载表格视图而不影响单元格中的倒数计时器
【发布时间】:2016-07-29 16:18:21
【问题描述】:

我有一个名为itemDisplayTableUITableView。其中的每个单元格都有一个倒数计时器和一个文本字段。每当值发生变化时,我希望使用来自服务器的数据更新文本字段。所以我每秒使用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”。

【问题讨论】:

  • 你从哪里加载你的倒计时计时器的值?
  • 我有一个日历按钮,我用它来设置倒数计时器的值。我只希望从服务器更新文本字段值。
  • 显示cellForRowAtIndex代码
  • @Abiranjan 我认为您没有为表格单元维护任何模型。建模将解决您的问题。只需更新您的文本字段值并保持倒计时..
  • 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 } }

标签: ios swift


【解决方案1】:
  1. 我希望文本字段在值发生变化时使用来自服务器的数据进行更新。所以我使用 NSTimer 每秒重新加载整个表格视图。

重新加载整个 tableView 不是这样做的方法;它很慢,特别是如果你有一张大桌子。有没有办法可以打开一个套接字来监听来自服务器的更改,并且只更新在服务器发送更改时更改的特定单元格?您可以使用以下命令重新加载特定单元格,其中 indexPathsArray 是一个 NSIndexPaths 数组,指向需要刷新的任何单元格:

tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths(indexPathsArray, withRowAnimation: UITableViewRowAnimation.None)
tableView.endUpdates()
  1. 有什么方法可以单独更新或重新加载单元格内的文本字段,或者避免倒数计时器显示“00:00:00”。

我建议为您的 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 数组。要在屏幕上显示这些更改,您可以刷新整个表格(但同样,只更新已更改的单元格会更有效)。

我希望这能给您一些关于如何解决问题的指导。

【讨论】:

  • 万岁!我创建了数据模型,但仍然没有帮助。我不是每秒重新加载一次,而是仅在数据发生变化并且它起作用时才重新加载表。不过谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-02
相关资源
最近更新 更多