定时器到期时Swift删除表视图单元格

时间:2016-07-13 09:43:58

标签: swift

我努力寻找解决方案,但我陷入困境。在每个单元格中有一个带定时器的自定义表视图。当计时器到期时,即使单元格在屏幕外,单元格也应该被删除,它应该被删除,不应该显示。

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! iDealCell
    //        cell.SponsorLogo.image = UIImage(named: "back.png")!
    cell.SponsorName.text = iDeals[indexPath.row].SponsorName;
    cell.Distance.text = iDeals[indexPath.row].Distance;
    cell.Type.text = iDeals[indexPath.row].Type;
    cell.iDealTimer.font = UIFont(name: "DBLCDTempBlack", size: 18.0)

    onHourFromNow = NSDate(timeInterval: 10, sinceDate: timeNow)
    let TimeDiffInSec = NSCalendar.currentCalendar().components(.Second, fromDate: timeNow, toDate: onHourFromNow, options: []).second
    cell.TimeDiffInSec = TimeDiffInSec
    cell.kickOffCountdown()
    cell.backgroundColor = UIColor.clearColor()
    cell.delegate = self
    return cell
}
  

在单元类中,有三个初始化和运行计时器的函数

func kickOffCountdown(){
    self.setCountDown()
    Timer.invalidate()
    Timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(iDealCell.setCountDown), userInfo: nil, repeats: true)                     
}

func secondsToHoursMinutesSeconds (seconds : Int) -> (String, String, String) {
    let hours = seconds / 3600
    let minutes = (seconds % 3600) / 60
    let seconds = (seconds % 3600) % 60

    let hoursString = hours < 10 ? "0\(hours)" : "\(hours)"
    let minutesString = minutes < 10 ? "0\(minutes)" : "\(minutes)"
    let secondsString = seconds < 10 ? "0\(seconds)" : "\(seconds)"
    return (hoursString, minutesString, secondsString)
}

func setCountDown() {
    if(TimeDiffInSec > 0) {
        let (h,m,s) = secondsToHoursMinutesSeconds(TimeDiffInSec)
        self.iDealTimer.text = "\(h):\(m):\(s)"
        TimeDiffInSec = TimeDiffInSec - 1
    }
    else{
        self.iDealTimer.text = "EXPIRED"
        if let delegate = self.delegate {
            delegate.DeleteiDealID(1)
        }
        Timer.invalidate()
    }
}

任何帮助都会得到很大的帮助

5 个答案:

答案 0 :(得分:0)

我认为,这将是更好的方式:

  1. tableView:cellForRowAtIndexPath内部计算(或获取)时间,并将其值添加到单元格中的标签。
  2. 从单元格中删除计时器。
  3. viewDidAppear(或获取数据的内部块)的主类(放置tableView)中添加计时器,这将是每秒调用方法,检查和删除过期的对象(或者您可以应用过滤器)和fire tableView.reloadData()(或删除所需的行动画)。
  4. viewDidDisappear无效计时器。

答案 1 :(得分:0)

只要你的时间到期,你可以做一些简单的事情,无论你用于行计数,你都可以从你的字典数组中删除这些值。

这里简单的事情就是你的所有表格单元格取决于你的行计数去除特定单元格,删除特定的数组对象。

示例:

if timerExpire == true {
        array.removeAtIndex(5)
        self.table.reloadData()
}

答案 2 :(得分:0)

这是一个棘手的问题,因为你想:

  1. 即使在计时器弹出时它们在屏幕外,也要删除表行。
  2. 可以添加新行,而旧行是&#34;勾选&#34;。
  3. 第一点意味着您不希望计时器保留在单元格中。无论如何,这是错误的地方,因为细胞被重复使用,你就会让梦魇失效并重新启动计时器。

    第二点表示在计时器启动时要删除的行号可能与计时器弹出时删除的行号不同。您可以在5秒内启动要删除的行5的计时器,但在此期间,行4会被删除,使前一行5现在排{{1} }}。当前一行4的计时器弹出时,需要从表中删除行5

    以下是我建议的方法:

    1. 为表格中的每一行指定一个唯一ID。这只是一个由4类维护的简单计数。

      UITableViewController
    2. 维护与您当前表中的行对应的活动ID列表。将此媒体资源添加到您的var nextID = 0

      UITableViewController
    3. 在表格中添加一个字典,将var activeIDs = [Int]() 映射到ID。将其添加到您的NSTimer

      UITableViewController
    4. 在表格中创建新行时:

      var timerIDmap: [NSTimer: Int]()
      
    5. let newID = nextID activeIDs.append(newID) nextID += 1 中,请务必将cellForRowAtIndexPath存储在单元格的属性中。

      ID
    6. 创建计时器时,需要将计时器及其对应的单元ID存储在cell.cellID = activeIDs[indexPath.row] 中。由于您将在自定义单元格中执行此操作,因此单元格需要对包含它的tableViewController具有弱引用:

      timerIDmap

      并在// add this property to your cell weak var myTableVC: UITableViewController? 中分配该属性:

      cellForRowAtIndexPath

      这样当您创建计时器时:

      cell.myTableVC = self
      
    7. 当您的计时器计时时,您需要减少该计时器剩余的时间。这意味着剩下的时间也应保留在您的模型中。将此词典添加到let timer = NSTimer.scheduledTimerWithTimerInterval(... myTableVC?.timerIDmap[timer] = cellID

      UITableViewController

      这意味着当您首先创建计时器时,您将timeLeft存储在此词典中

      var timeLeft = [Int: Int]()  // maps CellID to time left
      

      好的,现在你的handleCountdown例程应该在myTableVC?.timeLeft[cellID] = 50 // some appropriate value 中实现:

      UITableViewController
    8. 这为您的自定义单元格留下了很少的工作量。它应该只花费在计时器上留下的时间并将其格式化以便显示。在func handleCountdown(timer: NSTimer) { let cellID = timerIDMap[timer] // find the current row corresponding to the cellID let row = activeIDs.indexOf(cellID) // decrement time left let timeRemaining = timeLeft[cellID] - 1 timeLeft[cellID] = timeRemaining if timeRemaining == 0 { timer.invalidate timerIDmap[timer] = nil activeIDs.removeAtIndex(row) tableView.deleteRowsAtIndexPaths(NSIndexPath(row: row, section: 0), withRowAnimation: ... } else { tableView.reloadRowsAtIndexPaths(NSIndexPath(row: row, section: 0), withRowAnimation: ... } } 中,告诉单元格计时器还剩多少时间:

      cellForRowAtIndexPath
    9. 表中的项目数与cell.timeLeft = timeLeft[activeIDs[indexPath.row]] 中的项目数相同,因此在activeIDs返回

      tableView:numberOfRowsInSection

答案 3 :(得分:0)

我一直在尝试这些解决方案,但我认为它们不可能实现这一目标。只是想让人们知道。如果您找到了可行的或找到相同的东西,请告诉我们

答案 4 :(得分:0)

这是我提出的解决方案。然而,它无论如何都不是一个完美的解决方案,它确实解决了这个问题。

在viewcontroller中:

    func handleDate(timer: Timer) {


    DispatchQueue.main.async() {

        if self.posts.count < 1 {
            print("Empty")
            timer.invalidate()

        } else {

            let calendar = Calendar.current
            let date = Date()

            let componentsCurrent = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
            var components = DateComponents()

            components.hour = componentsCurrent.hour
            components.minute = componentsCurrent.minute
            components.second = componentsCurrent.second
            components.year = componentsCurrent.year
            components.month = componentsCurrent.month
            components.day = componentsCurrent.day
            let currentTime = calendar.date(from: components)!

            for post in self.posts {



                let cellID = post.postID
                let row = self.postsInFeed.index(of: cellID)

                let endDate = TimeInterval(post.time)



                if currentTime.timeIntervalSince1970 >= endDate {



                        self.tableView.beginUpdates()
                        timer.invalidate()

                        print(post.postID)
                        print("Deleting tableview row")

                        self.postsInFeed.removeFirst()
                        self.posts.removeFirst()

                        let store: Dictionary<String, Any> = ["caption": post.caption, "mediaURL": post.imageUrl as Any, "likes": post.likes, "user_ID": FriendSystem.system.CURRENT_USER_ID, "time": post.time]

                        let firebasePost = FriendSystem().GROUP_REF.child(self.group.groupID).child("storage").child(post.postID)
                        firebasePost.setValue(store)

                        FriendSystem().GROUP_REF.child(self.group.groupID).child("posts").child(cellID).removeValue()

                        self.tableView.deleteRows(at: [IndexPath(row: row!, section: 0)] , with: UITableViewRowAnimation.fade)
                        self.tableView.endUpdates()
                        self.tableView.reloadData()

                        }
                    }
                }
            }
    }

在tableviewcell中:

func tick(timer: Timer) {

    guard let expiresAt = endDate else {
        return
    }
    let calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)
    if let components = calendar?.components([.hour, .minute, .second], from: NSDate() as Date, to: expiresAt, options: []) {
        currentTime = formatDateComponents(components: components as NSDateComponents)
        self.timerLbl.text = currentTime

        if Date() >= endDate! {
            timer.invalidate()
        }

    }
}

func formatDateComponents(components: NSDateComponents) -> String {
    let hours = components.hour
    let minutes = components.minute
    let seconds = components.second

    return "\(hours):\(minutes):\(seconds)"
}