2017-08-22 35 views
-1

私のアプリでは、tableViewの各セルに異なるtimeIntervalを持つタイマーを設定し、timerを返すsetTimer関数を作成し、timerを無効にするprepareForReuse関数を作成しました。私はここにcellForRow関数内関数SETTIMERを呼び出すのViewControllerでタイマーが正常に動作しない

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() 
} 


} 

その

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 

構造体forShowedVC { のvar画像です:UIImage! var text:文字列! var秒:ダブル! var countTimes:Double! }

クラスshowedVC:の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 
} 


} 
+0

cell.cellTimer?.invalidate()への呼び出しを置くことができます。 cellForRowAtをいつも呼び出す回数を指定して、問題の原因となっていることを確認します。 –

+0

reloadData()を呼び出すすべてのセルでタイマーを実行するのは悪いことです。セルのタイマーが起動するたびに、テーブルビュー全体をリロードしています。 'reloadRows(at:with:)'を使って、どのセルが変更されたか把握し、それらのセルをリロードするだけでよいのです。 –

+0

すべてを変更してください。 –

答えて

0

は、問題は、セルをデキューするたびに、新しいタイマーを作成することですが、それらのいずれかを無効にすることはありません。その結果、コードをスクロールするとタイマーが増え続けます。ここで私はそれを修正するためにどうなるのかです:

は弱いオプションであるタイマー性質を持っているあなたのテーブルビューセルクラスを変更します。

@class cellForData: UITableViewCell { 

    weak var cellTimer: Timer? 

//Your other vars and code here 
} 

その後、あなたのcellForRowAt方法では、セルをデキューし、すぐにだ、それを無効にしますタイマー:タイマーが動作している間、タイマーに対する細胞のcellTimer弱いオプション、唯一の強い参照が実行ループによって保持させることで

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. 
} 

。それを無効にすると、解放されてnilに設定されます。したがって、コードcell.cellTimer?.invalidate()のオプションの連鎖は、セルに実行中のタイマーがない場合は何も行いません。

また、あなたのテーブルビューセルのprepareForReuse()方法ではなく、あなたの質問は、あなたが詳細に手の込んだしてくださいすることができそれほど明確ではないcellForRowAt

関連する問題