如何在Swift中使用NSTimer和NSNotificationCentre更新UITableViewCells

lea*_*ift 7 uitableview nstimer nsnotificationcenter ios swift

注意:请在Swift中寻求答案.

我正在做的事情:

  • 让tableview单元每1秒更新一次,并显示实时倒计时.

我目前是怎么做的:

  • 我有一个包含标签的单元格的tableview.

  • 生成单元格后,它们会调用一个函数来计算今天和存储的目标日期之间的时间,并显示标签中剩余的倒计时时间.

  • 为了让单元格每秒更新标签,我使用一个NSTimer每秒重新加载tableview.

  • 问题:倒计时有效,但是当我尝试执行"滑动到删除"操作时,因为NSTimer重新加载了tableview,它会重置刷过的单元格以便不再刷卡,当然这对最终用户来说是不可接受的.

我正在尝试/潜在的解决方案

  • 我听说更好的方法是使用NSNotificationCenter触发器NSTimer并为每个单元添加侦听器.每隔1秒发送一次"广播" NSNotificationCenter,小区将收到"广播"并更新标签.

  • 我尝试在代码中生成新单元格的每个单元格中添加一个侦听器:

    // Generate the cells
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
    var cell = tableView.dequeueReusableCellWithIdentifier("Tablecell", forIndexPath: indexPath) as UITableViewCell
    let countdownEntry = fetchedResultController.objectAtIndexPath(indexPath) as CountdownEntry
    
    // MARK: addObserver to "listen" for broadcasts
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateCountdownLabel", name: mySpecialNotificationKey, object: nil)
    
    func updateCountdownLabel() {
        println("broadcast received in cell")
        if let actualLabelCountdown = labelCountdown {
            // calculate time between stored date to today's date
            var countdownValue = CountdownEngine.timeBetweenDatesRealTime(countdownEntry.date)
            actualLabelCountdown.text = countdownValue
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 但观察者的选择器似乎只能在视图控制器级别而不是在单元格中定位功能.(我无法从单元格中触发"updateCountdownLabel".当我在视图控制器级别创建同名函数时,可以调用该函数)

问题

  • 所以我的问题是:这是正确的方法吗?
  • 如果是,我如何让监听器在单元级别触发函数?
  • 如果不是,那么在不中断Swipe on Cell操作的情况下实现此实时倒计时的最佳方法是什么?

在此先感谢您的帮助!

Mat*_*mbo 14

它可能是一种根本不重新加载细胞的解决方案.只需让单元格听取更新通知并相应地更改其标签.我假设你是子类UITableViewCell并给单元格一个storedDate属性.您将在准备单元格时设置该属性.

计时器只会触发通知.

请记住从通知中心取消注册单元格 dealloc

这是一个简单的例子.

包含TableView的View Controller:

class ViewController: UIViewController, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    var timer: NSTimer!


    //MARK: UI Updates

    func fireCellsUpdate() {
        let notification = NSNotification(name: "CustomCellUpdate", object: nil)
        NSNotificationCenter.defaultCenter().postNotification(notification)
    }

    //MARK: UITableView Data Source

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cellIdentifier = "CustomCell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! CustomTableViewCell
        cell.timeInterval = 20
        return cell
    }

    //MARK: View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.timer = NSTimer(timeInterval: 1.0, target: self, selector: Selector("fireCellsUpdate"), userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
    }


    deinit {
        self.timer?.invalidate()
        self.timer = nil
    }

}
Run Code Online (Sandbox Code Playgroud)

自定义单元子类:

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!

    var timeInterval: NSTimeInterval = 0 {
        didSet {
            self.label.text = "\(timeInterval)"
        }
    }

    //MARK: UI Updates

    func updateUI() {
        if self.timeInterval > 0 {
            --self.timeInterval
        }
    }

    //MARK: Lifecycle

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code

        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.addObserver(self, selector: Selector("updateUI"), name: "CustomCellUpdate", object: nil)
    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

}
Run Code Online (Sandbox Code Playgroud)

我很确定这个例子不符合你应用的逻辑.只是展示事物是如何一起发光的.