2017-02-10 7 views
0

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

Antwort

1

beste Weg, um eine Zeit wie dieser ist zu planen und zu verwenden:

//schedules timer at an 4 seconds interval + pass desired userInfo 
var myTimer = Timer.scheduledTimer(timeInterval: 4.0 
     , target: self, selector: #selector(timerSelector), userInfo: nil, repeats: true) 

//timer selector peform your actions there and 
func timerSelector(dt:Timer){ 
} 

//invalidate timer when needed like this 
myTimer?.invalidate() 

auch wieder der Timer nur neu zu planen rufen Timer.scheduledTimer

+0

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

+0

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

+0

haben Post bearbeitet. Ich verstehe, dass das nicht ideal ist, aber es ist das, woran ich gerade arbeite. – Pippo

Verwandte Themen