2016-07-29 11 views
0

Ich downloade Dateien in Swift, und die Download-Sitzung wird durch eine Schaltfläche in jeder Tabellenansicht Zelle ausgelöst. Ich möchte jedoch nicht, dass der nächste Download (wenn jemand auf den Download-Knopf in einer anderen Zelle drückt) geschieht, bis der vorherige fertig ist.Versand nach Download ist in Swift abgeschlossen?

Gibt es eine Möglichkeit, dass ich etwas wie dispatch_after verwenden kann, um dies zu erreichen?

Hier ist mein Code, wo das Herunterladen erfolgt, wenn es überhaupt hilft.

//FUNCTION TO DOWNLOAD THE PDF 
//PASS THE ONLINE PDF URL AS NSURL 
//ASYNC REQUEST 
let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 
var dataTask: NSURLSessionDataTask? 
var temp_name = String() 
var temp_index = Int() 
var temp_indexPath = NSIndexPath() 

lazy var downloadsSession: NSURLSession = { 

    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() 
    let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil) 
    return session 
}() 
func getUrl(name: String) -> NSURL?{ 
    let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL! 
    return documentsUrl.URLByAppendingPathComponent(name) 
} 

func getIndex() -> Int?{ 
    return temp_index 
} 

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) { 

    if let originalURL = downloadTask.originalRequest?.URL?.absoluteString, 
     destinationURL = getUrl(temp_name){ 

     let fileManager = NSFileManager.defaultManager() 
     do { 
      try fileManager.removeItemAtURL(destinationURL) 
     } catch { 
      // Non-fatal: file probably doesn't exist 
     } 
     do { 
      try fileManager.copyItemAtURL(location, toURL: destinationURL) 
     } catch let error as NSError { 
      print("Could not copy file to disk: \(error.localizedDescription)") 
     } 
    } 


    if let url = downloadTask.originalRequest?.URL?.absoluteString { 
     activeDownloads[url] = nil 

     if let trackIndex = getIndex() { 
      dispatch_async(dispatch_get_main_queue(), { 
       defaults.setBool(false, forKey: self.temp_name + "_downloading") 


       self.tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: trackIndex, inSection: 0)], withRowAnimation: .None) 
      }) 
     } 
    } 


} 


func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { 

    if let downloadUrl = downloadTask.originalRequest?.URL?.absoluteString, 
     download = activeDownloads[downloadUrl] { 
     download.progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite) 
     if let trackIndex = getIndex(), let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: trackIndex, inSection: 0)) as? MainTableViewCell { 
      dispatch_async(dispatch_get_main_queue(), { 
       cell.progress.progress = download.progress 
       if(download.progress < 1.0){ 
        cell.progress.hidden = false 
       } 
       else{ 
        cell.progress.hidden = true 
       } 
      }) 
     } 

    } 

} 

// Action triggered by UIButton (in this case the download button) 
//Access tag, which is the IndexPath.row, using sender.tag 
@IBAction func downloadFile(sender: UIButton){ 
    let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0) 
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MainTableViewCell 
    cell.downloadButton.hidden = true 
    cell.progress.progress = 0 
    cell.progress.hidden = false 



    let isAvailable = true 
    let key = names[sender.tag] + "_offline" 
    defaults.setValue(isAvailable, forKey: key) 
    let name = (names[sender.tag]) 
    let fileName = name + ".pdf" 
    let attachment = attachments[sender.tag] 
    temp_name = fileName 
    temp_index = sender.tag 
    temp_indexPath = indexPath 
    let destinationURL = getUrl(temp_name)! 
    defaults.setValue(destinationURL.path!, forKey: name + "_path") 
    defaults.synchronize() 
    defaults.setBool(true, forKey: name + "_downloading") 
    let urlString = attachment 
    let url = NSURL(string: urlString) 

    let download = PDFDownload(url: urlString) 

    download.downloadTask = downloadsSession.downloadTaskWithURL(url!) 
    download.downloadTask!.resume() 
    download.isDownloading = true 

    activeDownloads[download.url] = download 

} 

Es gibt einen boolean, das speichert, ob eine Download-Sitzung auftritt, vielleicht gibt es eine Möglichkeit, dass ich das nicht verwenden kann? Warte, bis der Boolesche Wert falsch ist, um meinen Code auszuführen?

+0

Sie die Taste deaktivieren kann, nachdem er das erste Mal und es wieder aktivieren in dem Abschluss-Handler für Ihr Netzwerk Anruf –

+0

Lassen Sie mich auf jedem Tisch Sichtzelle, und ich möchte noch die andere clarify- sie sind Tasten angeklickt wird Arbeiten, aber nur warten bis zum Download –

+0

ah, eine Sache, die Sie dann tun könnten, ist eine serielle dispatch_queue zu verwenden, oder Sie könnten es in eine NSOperation wickeln und eine serielle NSOperation Queue verwenden –

Antwort

2

@Deepak Kumar Antwort ist korrekt, aber hinzufügen Abhängigkeit für jede Operation ist keine gute Idee. Sie können es auf eine einfachere Art und Weise tun. nur 3 Schritte erforderlich.

  1. NSOperationQueue-Objekt erstellen.
  2. dann setzen Sie die Eigenschaft maxConcurrentOpeations auf 1.
  3. dann hinzufügen Operationen in die Warteschlange, wird es die Operationen nacheinander ausführen.
+0

Awesome - das macht mehr Sinn –

2

Sie können NSOperationQueue verwenden, um dies zu erreichen. Erstellen Sie eine Operationswarteschlange und ein NSOperation-Objekt zum Speichern der vorherigen Operation, die vor der aktuellen Operation zur Operationswarteschlange hinzugefügt wurde. Klicken Sie bei jedem Klick auf die Schaltfläche TableViewcell eine neue NSOperation-Instanz an und führen Sie die folgenden Schritte durch, bevor Sie sie zur Operationswarteschlange hinzufügen.

1 - prüfen, ob die Temperatur nicht abgelaufen ist. Ordnen Sie ihr dann die aktuelle Operation zu und fügen Sie sie zur Operationswarteschlange hinzu. 2. andernfalls zuerst die Abhängigkeit von der temporären Operation hinzufügen, dann die aktuelle Operation zuweisen und dann zur Operationswarteschlange hinzufügen.

Auf diese Weise wird jede Aufgabe nach Abschluss der vorherigen Aufgabe gestartet. Hoffe das wird dir helfen. :)

Verwandte Themen