注意:请在 Swift 中寻求答案。
我想做的事情:
我目前的表现如何:
我有一个包含标签的单元格的tableview。
生成单元格时,它们会调用一个函数来计算今天和存储的目标日期之间的时间,并显示标签中剩余的倒计时时间。
为了让细胞每秒更新标签,我
使用NSTimer
每秒重新加载tableview。
问题:倒计时有效,但当我尝试执行“刷卡到删除”操作时,因为NSTimer
重新加载了表格视图,它会重置
刷过单元格以便不再刷卡,当然这对最终用户来说是不可接受的。
我尝试/潜在解决方案
我听说更好的方法是使用由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
}
}
但观察者的选择器似乎只能在视图控制器级别而不是在单元格中定位功能。 (我无法获取" updateCountdownLabel"从单元格中触发。当我在视图控制器级别创建同名函数时,可以调用该函数)
问题
提前感谢您的帮助!
答案 0 :(得分:14)
这可能是一种根本不重新加载细胞的解决方案。只需让单元格听取更新通知并相应地更改其标签。
我假设你是子类UITableViewCell
并给单元格一个storedDate
属性。您将在准备单元格时设置该属性。
计时器只会触发通知。
请务必在dealloc
这是一个简单的例子。
包含TableView的视图控制器:
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
}
}
自定义单元格子类:
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)
}
}
我很确定此示例不符合您应用的逻辑。只是展示一起如何发光。
答案 1 :(得分:1)
正如Ian MacDonald所建议的那样,如果你正在滑动,你应该避免在计时器滴答时重新加载细胞。同时删除NSNotification,因为它和计时器本质上是做同样的事情