ios - 重新加载表格 View 而不影响单元格中的倒数计时器

标签 ios swift

我有一个名为 itemDisplayTableUITableView。其中的每个单元格都有一个倒计时计时器和一个文本字段。我希望只要值发生变化,文本字段就可以使用来自服务器的数据进行更新。所以我使用 NSTimer 每秒重新加载整个 TableView 。

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()
}

表格 View 代码:

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. 我希望每当值发生变化时,文本字段都用来自服务器的数据进行更新。所以我使用 NSTimer 每秒重新加载整个 TableView 。

重新加载整个 tableView 不是这样做的方法;它很慢,特别是如果你有一张大 table 。有没有一种方法可以打开一个套接字来监听服务器的变化,并且只更新服务器发送变化时发生变化的特定单元格?您可以使用以下方法重新加载特定的单元格,其中 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% 确定您从问题中所做的事情。)

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

我希望这能为您提供一些解决问题的指导。

关于ios - 重新加载表格 View 而不影响单元格中的倒数计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38663348/

相关文章:

ios - 如何从一个类调用另一个类的方法(iOS)

ios - 将 Node 放置在 ARKit World 中的触摸位置

swift - 当我向下滚动并返回时,我的数据在 UITableViewCell 中发生变化

swift - 格式化后从字符串中删除空格

swift - 当用户在另一个应用程序中返回到我的应用程序时刷新 UIViewController

swift - 在 Swift 3.0 中使用 URLSession DownloadTask 时,多个下载不起作用

ios - 更新了 Parse SDK,获取 "' init( PFFile 为 )' is unavailable"

ios - 从 Unix 时间戳日期 ios 数组在 Uitableview 中创建动态部分?

ios - 如何在 iOS 8 中自定义 UIAction Sheet

iphone - 为什么将单元格图像添加到 UITableViewCell 会发出警告?