Ich habe einen Timer, den ich von innerhalb einer Schließung ausgeführt werde, um einige UI Update (Fortschrittsbalken) zu helfen. Es funktioniert für das erste Element, aber ich möchte, dass es für mehrere Elemente funktioniert. Also jedes Mal, wenn die Schließung ausgeführt wird, wird eine neue Instanz des Timers ausgeführt und die neue userInfo.Invalidieren und neue Instanz des Timers erstellen
// dispatch and add run loop to get it to fire
DispatchQueue.main.async(execute: {
timer = Timer.init(timeInterval: 0.25, target: self, selector: #selector(self.downloadTimer(_:)), userInfo: [innerCell, collectionView, indexPath], repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.defaultRunLoopMode)
})
Wenn diese Funktion unten beendet ist i der Timer neu erstellt werden soll, und neue userinfo an den Wähler passieren ..
func downloadTimer(_ timer: Timer) {
// need to pass arguments to timer as array inside userInfo
// then create dictionary and extract
let dict = timer.userInfo as! NSArray
let cell = dict[0] as! InnerCollectionCell
let collectionView = dict[1] as! UICollectionView
let indexPath = dict[2] as! IndexPath
// the index path isnt getting reset
// without casting the progress bar in each cell was displaying when coming back to DownloadCollectionController
if let downloadingCell = collectionView.cellForItem(at: indexPath) as? InnerCollectionCell {
DispatchQueue.main.async(execute: {
downloadingCell.progressBar.isHidden = false
downloadingCell.contentView.bringSubview(toFront: cell.progressBar)
downloadingCell.progressBar.setProgress(downloadProgress, animated: true)
downloadingCell.setNeedsDisplay()
if downloadProgress >= 1.0 {
print("TIMER STOPPED")
downloadingCell.progressBar.isHidden = true
//downloadQueue.operations[0].cancel()
timer.invalidate()
collectionView.reloadItems(at: [indexPath])
}
})
}
}
der Verschluss mit dem Timer = Timer wird erneut ausgeführt, aber die neue Benutzerinformationen werden nicht an den Zeitgeber übergeben, sondern werden nur mit der ursprünglichen Benutzerinfo ausgeführt. Wenn ich den Timer ungültig mache, kann er nicht mehr ausgelöst werden?
Ive versuchte es lokal auf dem ersten Brand zu schaffen:
var timer = Timer()
timer = Timer.init(timeInterval: 0.25, target: self, selector: #selector(self.downloadTimer(_:)), userInfo: [innerCell, collectionView, indexPath], repeats: true)
Aber es neu nicht den Timer, und ich will es stoppen können, wenn der Benutzer die Viewcontroller verlässt.
Gibt es einen besseren Weg, dies zu erreichen? Ich weiß, dass du nicht in der Lage sein solltest, einen Timer zurückzuziehen. Es muss eine Möglichkeit geben, jedes Mal eine einzigartige Instanz davon zu erstellen.
---- ---- EDIT
Dies ist, was die Pfade Index drucken, wie:
[0, 5]
[0, 5]
[0, 5]
[0, 5]
[0, 2]
[0, 5]
[0, 2]
[0, 1]
[0, 1]
[0, 1]
[0, 1]
So ist es eine Weile, nehmen Sie die Zeit und in dieser Zeit ungültig zu machen, der Timer wurde Wieder gefeuert und die Funktion des alten Indexpfad bis Fortschritt wird mit = 1
---- ---- EDIT
die einzigen Ort, Entwertung stattfindet, wenn Fortschritt> = 1
if downloadProgress >= 1.0 {
timer.invalidate()
downloadingCell.progressBar.isHidden = true
downloadingCell.progressBar.progress = 0
collectionView.reloadData()
}
Dann, weil der Timer aus cellForItemAt ausgelöst wird, wenn die Zelle bestimmte Bedingungen erfüllt, wenn collectionView.reloadData() der Zeitgeber genannt wird, sollte erneut validiert werden und die aktualisierte userinfo gesendet.
Das ist also der Block innerhalb cellForItemAt:
for operation in downloadQueue.operations {
if operation.name == self.multiPartArray[collectionView.tag][indexPath.item].name {
// edits for all queued operations
innerCell.spinner.isHidden = false
innerCell.spinner.startAnimating()
innerCell.contentView.bringSubview(toFront: innerCell.spinner)
innerCell.spinner.activityIndicatorViewStyle = .gray
innerCell.spinner.color = UIColor.darkGray
// hide the progress on all in queue it will be pushed to front when needed
innerCell.progressBar.isHidden = true
if operation.name == downloadQueue.operations[0].name {
// edits for the active downlaod in queue
// hide the spinner for currently downloading cell
// innerCell.spinner.isHidden = true
innerCell.spinner.isHidden = false
innerCell.spinner.startAnimating()
innerCell.contentView.bringSubview(toFront: innerCell.spinner)
innerCell.spinner.activityIndicatorViewStyle = .gray
innerCell.spinner.color = UIColor.blue
DispatchQueue.main.async(execute: {
let timer = Timer.init(timeInterval: 0.5, target: self, selector: #selector(self.downloadTimer(_:)), userInfo: [innerCell, collectionView, indexPath, collectionView.tag], repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.defaultRunLoopMode)
})
break
} else {
// edits spinner that isnt currently downloading
innerCell.progressBar.isHidden = true
innerCell.spinner.color = UIColor.darkGray
}
} else {
// edits the spinner that isnt in queue
innerCell.progressBar.isHidden = true
innerCell.spinner.color = UIColor.darkGray
}
}
ich seine nicht die eleganteste Lösung realisieren, aber ich habe verschachtelte Sammlung Ansichten habe, die wahrscheinlich nicht ganz für eine Arbeit richtig so krank settle eingerichtet wurde um in diesem Fall.
Und die downloadTimer:
func downloadTimer(_ timer: Timer) {
// need to pass arguments to timer as array inside userInfo
// then create dictionary and extract
let dict = timer.userInfo as! NSArray
let cell = dict[0] as! InnerCollectionCell
let collectionView = dict[1] as! UICollectionView
let indexPath = dict[2] as! IndexPath
let tag = dict[3] as! Int
print(indexPath)
// without casting the progress bar in each cell was displaying when coming back to DownloadCollectionController
if let downloadingCell = collectionView.cellForItem(at: indexPath) as? InnerCollectionCell {
// self.outerCollectionView.reloadItems(at: [IndexPath(item: tag, section: 0)])
DispatchQueue.main.async(execute: {
downloadingCell.spinner.isHidden = true
downloadingCell.progressBar.isHidden = false
downloadingCell.contentView.bringSubview(toFront: cell.progressBar)
downloadingCell.progressBar.setProgress(downloadProgress, animated: true)
downloadingCell.setNeedsDisplay()
if downloadProgress >= 1.0 {
timer.invalidate()
downloadingCell.progressBar.isHidden = true
downloadingCell.progressBar.progress = 0
collectionView.reloadData()
}
})
}
}
Sein eine während der Einnahme entwerten. Ich habe die Frage bearbeitet, um einige Ausdrucke des IndexPfads zu zeigen, die ich an den Timer übergebe. – Pippo
Drucken ist keine genaue Art, die Zeit zu zeigen, die eine Ausführung dauert ...aber wahrscheinlich ist es ein bisschen langsam, weil du etwas extra Ausführung machst, könntest du bitte deinen Post editieren um zu zeigen, wo und wie du den Timer annullierst und neu planst, weil es so aussieht als würdest du nur ungültig machen wenn 'downloadProgress> = 1.0'? – John
haben Post bearbeitet. Ich verstehe, dass das nicht ideal ist, aber es ist das, woran ich gerade arbeite. – Pippo