计时器无法正常工作

时间:2017-08-22 15:38:52

标签: ios swift uitableview timer

在我的应用程序中,我为tableView中的每个单元格设置了不同timeInterval的计时器,我创建了计时器数组,创建了返回Timer的函数setTimer和prepareForReuse使这里的计时器无效是我的自定义表格视图单元格类

class cellForData: UITableViewCell {

@IBOutlet weak var iconImage: UIImageView!

@IBOutlet weak var dataText: UILabel!


var timerArray: Array = [Timer(), Timer(), Timer(), Timer(), Timer(), Timer(), Timer(), Timer(), Timer(), Timer()]


var count: Double = 0
var texts = String()

var countHowMuch = Double()

func setTimer(withInterval: Double, text: String, countTimes: Double) -> Timer {
    texts = text
    countHowMuch = countTimes
    return Timer.scheduledTimer(timeInterval: withInterval, target: self, selector: #selector(handle), userInfo: nil, repeats: true)
}


func handle() {
    count += countHowMuch
    dataText.text = "\(count) + \(texts)"
}

override func prepareForReuse() {
    super.prepareForReuse()
    timerArray[timerArray.count - 1].invalidate()
}


}

在ViewController中,我在cellForRow函数中调用函数setTimer,这是

的代码
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if let cell = tableView.dequeueReusableCell(withIdentifier: "secondVCCell") as? cellForData {
        cell.timerArray[indexPath.row] = cell.setTimer(withInterval: arrayOfAStruct[indexPath.row].seconds, text: arrayOfAStruct[indexPath.row].text, countTimes: arrayOfAStruct[indexPath.row].countTimes)
        RunLoop.main.add(cell.timerArray[indexPath.row], forMode: .commonModes)

        return cell
    }

    return UITableViewCell()

}

因此,当表格视图滚动的单元格表现奇怪时,这些单元格总是会改变位置,在此之后定时器无法正常工作,我猜计时器甚至不会失效。每当单元格重用并且单元格保持在相同位置时,我需要定时器无效。这是我的整个视图控制器

import UIKit

struct forShowedVC {     var image:UIImage!     var text:String!     var秒:双倍!     var countTimes:双倍! }

class showsVC:UIViewController,UITableViewDataSource,UITableViewDelegate {

@IBOutlet weak var myTableView: UITableView!

var arrayOfAStruct = [forShowedVC]()


override func viewDidLoad() {
    super.viewDidLoad()
    myTableView.dataSource = self
    myTableView.delegate = self

    arrayOfAStruct = [forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "a", seconds: 1, countTimes: 3),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "b", seconds: 1, countTimes: 2),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "c", seconds: 1, countTimes: 7),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "d", seconds: 1, countTimes: 12),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "e", seconds: 1, countTimes: 1),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "f", seconds: 1, countTimes: 9),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "g", seconds: 1, countTimes: 13),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "h", seconds: 1, countTimes: 71),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "i", seconds: 1, countTimes: 4),
                      forShowedVC(image: #imageLiteral(resourceName: "pie-chart"), text: "j", seconds: 1, countTimes: 6)]
    }


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if let cell = tableView.dequeueReusableCell(withIdentifier: "secondVCCell") as? cellForData {
        cell.timerArray[indexPath.row] = cell.setTimer(withInterval: arrayOfAStruct[indexPath.row].seconds, text: arrayOfAStruct[indexPath.row].text, countTimes: arrayOfAStruct[indexPath.row].countTimes)
        RunLoop.main.add(cell.timerArray[indexPath.row], forMode: .commonModes)

        return cell
    }

    return UITableViewCell()

}



func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return arrayOfAStruct.count
}


}

1 个答案:

答案 0 :(得分:0)

问题在于每次出列单元格时都会创建一个新计时器,但永远不会使其中任何一个无效。因此,当您滚动代码时,会不断添加更多计时器。以下是我要采取的措施:

将表视图单元类修改为具有弱可选的计时器属性:

@class cellForData: UITableViewCell {

  weak var cellTimer: Timer?

//Your other vars and code here
}

然后在你的cellForRowAt方法中,将一个单元格出列并立即使它无效的计时器:

if let cell = tableView.dequeueReusableCell(withIdentifier: "secondVCCell") as? cellForData {
    cell.cellTimer?.invalidate()
    cell.cellTimer = setTimer(withInterval: arrayOfAStruct[indexPath.row].seconds, selector: #selector(handleObject))
    //The rest of your code to configure the cell goes here.
}

通过使单元格cellTimer成为弱可选项,在计时器运行时,运行循环将保留对计时器的唯一强引用。如果您使其无效,它将被释放并设置为nil。因此,如果单元格没有正在运行的计时器,则代码cell.cellTimer?.invalidate()中的可选链接不会执行任何操作。

您也可以在表格查看单元格cell.cellTimer?.invalidate()方法中调用prepareForReuse(),而不是cellForRowAt