重新加载表格视图而不影响单元格中的倒数计时器

时间:2016-07-29 16:18:22

标签: ios swift

我有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"。

1 个答案:

答案 0 :(得分:1)

  1. 我希望每当值发生变化时,都会使用服务器中的数据更新文本字段。所以我每秒使用NSTimer重新加载整个表视图。
  2. 重新加载整个tableView不是这样做的方法;它很慢,特别是如果你有一张大桌子。有没有办法可以打开套接字来监听服务器的更改,只更新服务器发送更改时更改的特定单元格?您可以使用以下命令重新加载特定单元格,其中indexPathsArray是指向需要刷新的任何单元格的NSIndexPaths数组:

    tableView.beginUpdates()
    tableView.reloadRowsAtIndexPaths(indexPathsArray, withRowAnimation: UITableViewRowAnimation.None)
    tableView.endUpdates()
    
    1. 有没有办法在单元格内单独更新或重新加载文本字段,或者避免倒数计时器显示“00:00:00”。
    2. 我建议为您的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数组。要在屏幕上显示这些更改,您可以刷新整个表格(尽管如此,仅更新已更改的单元格会更有效。)

      我希望这能为您提供有关如何解决问题的指导。