【发布时间】:2015-10-10 17:57:55
【问题描述】:
我正在开发一个计时器应用程序。如此处所示Timer App。此计时器应用程序与自定义 UIView 单元一起使用。一切正常,直到您创建的计时器(单元格)比显示的多。例如,假设我添加了 15 个计时器,其中 10 个显示(显示在屏幕上),而 5 个不显示。如果我启动其中一个计时器,然后向下滚动以显示其余计时器,您将看到其中一个计时器已经在运行,而无需手动启动它。好像它被复制了一样。我确实知道系统会重用单元格。我怎样才能避免这种情况?我怎样才能使计时器无论有多少都单独工作?
TimerTableViewCell: UITableViewCell,UITextFieldDelegate {
// MARK: - Properties
var time = 30
var displayTime = 30
var counterRun = NSTimer()
var startTime = NSTimeInterval()
var currentTime = NSTimeInterval()
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var startLabel: UIButton!
@IBOutlet weak var numberText: UITextField!
@IBOutlet weak var buttonImage: UIButton!
// MARK: - Defaults
override func awakeFromNib() {
super.awakeFromNib()
/// Initialization code
numberText.delegate = self
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
/// Configure the view for the selected state
}
// MARK: Delegate Function
func textFieldShouldReturn(textField: UITextField) -> Bool {
/// Hide the keyboard
numberText.resignFirstResponder()
return true
}
// MARK: Actions
@IBAction func startButton(sender: UIButton) {
/// Makes time run
if displayTime == 0 {
time = 30
displayTime = 30
timeLabel.text = "\(displayTime)"
counterRun = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timeRunner", userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
startLabel.selected = true
startLabel.setImage(UIImage(named: "Stop"), forState: .Selected)
}
else if startLabel.selected == true {
startLabel.selected = false
startLabel.setImage(UIImage(named: "Start"), forState: .Normal)
counterRun.invalidate()
time = displayTime
}
else {
startLabel.selected = true
startLabel.setImage(UIImage(named: "Stop"), forState: .Selected)
counterRun = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timeRunner", userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
}
}
func timeRunner(){
currentTime = NSDate.timeIntervalSinceReferenceDate()
let elapsedTime: NSTimeInterval = currentTime - startTime
///calculate the minutes in elapsed time.
let minutes = UInt8(elapsedTime / 1)
let minutesInt = Int(minutes)
displayTime = time - minutesInt
timeLabel.text = "\(displayTime)"
timeStopper()
}
func timeStopper(){
if displayTime <= 0 {
startLabel.selected = false
startLabel.setImage(UIImage(named: "Start"), forState: .Normal)
counterRun.invalidate()
}
}
@IBAction func refreshButton(sender: UIButton) {
startLabel.selected = false
startLabel.setImage(UIImage(named: "Start"), forState: .Normal)
time = 30
displayTime = 30
timeLabel.text = "\(displayTime)"
counterRun.invalidate()
}
@IBAction func changePhoto(sender: UIButton) {
let duckPhoto = UIImage(named: "Duck")
let swanPhoto = UIImage(named: "Swan")
/// Changes the photo of the cell.
if buttonImage.selected == false {
buttonImage.selected = true
buttonImage.setImage(swanPhoto, forState: .Selected)
}
else if buttonImage.selected == true {
buttonImage.selected = false
buttonImage.setImage(duckPhoto, forState: .Normal)
}
}
}
这是 UITableViewController
class TimerTableViewController: UITableViewController {
// MARK: - Properties
var timers = [Time]()
override func viewDidLoad() {
super.viewDidLoad()
/// Uncomment the following line to preserve selection between presentations
/// self.clearsSelectionOnViewWillAppear = false
/// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
/// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return timers.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "TimerCell"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! TimerTableViewCell
let time = timers[indexPath.row]
cell.timeLabel.text = "\(time.time)"
cell.buttonImage.setImage(time.photo, forState: .Normal)
return cell
}
/// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
/// Return false if you do not want the specified item to be editable.
return true
}
/// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
/// Delete the row from the data source
timers.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
/// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
/// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
/// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
/// Return false if you do not want the item to be re-orderable.
return true
}
// MARK: Actions
@IBAction func addButton(sender: UIBarButtonItem) {
let photo = UIImage(named: "Duck")
let time = Time(time: 30, photo: photo!)
let newIndexPath = NSIndexPath(forRow: timers.count, inSection: 0)
timers.append(time)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
}
}
以及制作计时器对象的类
class Time {
let time: Int
let photo: UIImage
init(time: Int, photo: UIImage){
self.time = time
self.photo = photo
}
}
谢谢
【问题讨论】:
-
听起来你让初学者在细胞和细胞重用方面犯了错误。也不清楚你在用计时器做什么。你是在说
NSTimers 吗?您是否为每个单元格创建一个?他们在做什么?他们调用什么方法,当您说“显示计时器”时,您是什么意思?发布代码的相关部分,否则我们将无法为您提供帮助。 -
我确信我犯了初学者的错误。 “显示”意味着它正在屏幕上显示。不,我不会为每个单元格创建一个。我将更新我的问题并添加代码。感谢回复 !期待有帮助的答案!
-
@DuncanC 我刚刚添加了代码。谢谢
-
好的,您已经发布了自定义 UITableViewCell 子类的代码。现在您的表格视图数据源方法的代码如何?(cellForRowAtIndexPath 等)
-
@DuncanC 在那里,我已经添加了我拥有的所有东西。
标签: ios swift uitableview uiview timer