2015-12-14 23 views
5

Alamofire viene utilizzato per scaricare più file di grandi dimensioni in una sola richiesta. Sono in grado di fare progressi visibili per ogni file separatamente utilizzandoIntera sessione download progress Alamofire

Alamofire.request(.GET, imageURL).progress 

ma vorrei per monitorare lo stato di avanzamento di tutte le sessioni aperte in una sola volta e non so come fare. (diciamo che ho 15 download di file simultaneamente) Ho letto un sacco di tutorial che affrontano il progresso di un singolo file, ma per l'intera sessione nessuno.

È possibile tenere traccia dei progressi in questo modo con Alamofire e, in caso affermativo, come?

risposta

4

In iOS9, è possibile creare il proprio oggetto NSProgress e osservare, ad esempio, fractionCompleted. Poi si può addChild:

private var observerContext = 0 

class ViewController: UIViewController { 

    private var progress: NSProgress! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     progress = NSProgress() 
     progress.addObserver(self, forKeyPath: "fractionCompleted", options: .New, context: &observerContext) 

     downloadFiles() 
    } 

    deinit { 
     progress?.removeObserver(self, forKeyPath: "fractionCompleted") 
    } 

    private func downloadFiles() { 
     let filenames = ["as17-134-20380.jpg", "as17-140-21497.jpg", "as17-148-22727.jpg"] 

     let baseURL = NSURL(string: "http://example.com/path")! 

     progress.totalUnitCount = Int64(filenames.count) 
     progress.completedUnitCount = 0 

     for filename in filenames { 
      let url = baseURL.URLByAppendingPathComponent(filename) 
      let childProgress = Alamofire.request(.GET, url.absoluteString) 
       .response() { request, response, data, error in 
        // process response 
       } 
       .progress 
      progress.addChild(childProgress, withPendingUnitCount: 1) 
     } 
    } 

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 
     if context == &observerContext { 
      if keyPath == "fractionCompleted" { 
       let percent = change![NSKeyValueChangeNewKey] as! Double 
       print("\(percent)") 
      } 
     } else { 
      super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) 
     } 
    } 

} 

Se avete bisogno di supporto per iOS 7/8, troppo, è possibile chiamare becomeCurrentWithPendingUnitCount e resignCurrent:

for filename in filenames { 
    let url = baseURL.URLByAppendingPathComponent(filename) 
    progress.becomeCurrentWithPendingUnitCount(1) 
    Alamofire.request(.GET, url.absoluteString) 
     .response() { request, response, data, error in 
      // process response 
    } 
    progress.resignCurrent() 
} 

Se si utilizza AFNetworking, è lo stesso processo (vale a dire gli stessi metodi viewDidLoad, observeValueForKeyPath e deinit come sopra), ma anziché recuperare la proprietà Alamofire progress, si utilizza invece il metodo AFHTTPSessionManagerdownloadProgressForTask per ottenere lo NSProgress associato allo NSURLSessionTask. Per esempio:

private func getFiles() { 
    let filenames = ["as17-134-20380.jpg", "as17-140-21497.jpg", "as17-148-22727.jpg"] 

    let manager = AFHTTPSessionManager() 
    manager.responseSerializer = AFHTTPResponseSerializer() 

    let baseURL = NSURL(string: "http://example.com/path")! 

    progress.totalUnitCount = Int64(filenames.count) 
    progress.completedUnitCount = 0 

    for filename in filenames { 
     let url = baseURL.URLByAppendingPathComponent(filename) 
     let task = manager.GET(url.absoluteString, parameters: nil, progress: nil, success: { task, responseObject in 
      // do something with responseObject 
      print(url.lastPathComponent! + " succeeded") 
     }, failure: { task, error in 
      // do something with error 
      print(error) 
     }) 

     if let downloadTask = task, let childProgress = manager.downloadProgressForTask(downloadTask) { 
      progress.addChild(childProgress, withPendingUnitCount: 1) 
     } 
    } 
} 

Oppure, se si utilizza le attività di download:

private func downloadFiles() { 
    let filenames = ["as17-134-20380.jpg", "as17-140-21497.jpg", "as17-148-22727.jpg"] 

    let manager = AFHTTPSessionManager() 

    let baseURL = NSURL(string: "http://example.com/path")! 

    progress.totalUnitCount = Int64(filenames.count) 
    progress.completedUnitCount = 0 

    let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) 

    for filename in filenames { 
     let url = baseURL.URLByAppendingPathComponent(filename) 
     let task = manager.downloadTaskWithRequest(NSURLRequest(URL: url), progress: nil, destination: { (temporaryURL, response) -> NSURL in 
      return documents.URLByAppendingPathComponent(url.lastPathComponent!) 
     }, completionHandler: { response, url, error in 
      guard error == nil else { 
       print(error) 
       return 
      } 

      if let name = url?.lastPathComponent { 
       print("\(name) succeeded") 
      } 
     }) 

     if let childProgress = manager.downloadProgressForTask(task) { 
      progress.addChild(childProgress, withPendingUnitCount: 1) 
     } 

     task.resume() 
    } 
} 
+0

Great thanks, funziona come fascino. –

+0

Ciao Rob, puoi fare un esempio con AFNetworking 3.0 per l'avanzamento di download di più file? – Nuibb

+1

@Nuibb - Questa dovrebbe essere una domanda separata, ma ho aggiornato la mia risposta illustrando gli esempi di AFNetworking ... – Rob