2014-03-03 4 views
7

Ich habe NSURLSession verwendet, um eine einzelne Datei herunterzuladen und es funktioniert gut, Jetzt muss ich drei Dateien im Hintergrund herunterladen und müssen auch ihre Fortschritte verwalten UIProgress.My Code für einzelne Downloads unter ..Herunterladen von mehr als einer Datei Mit NSURLSession und auch ihren Fortschritt im Hintergrund beibehalten

- (IBAction)startBackground:(id)sender 
{ 
    // Image CreativeCommons courtesy of flickr.com/charliematters 
    NSString *url = @"http://farm3.staticflickr.com/2831/9823890176_82b4165653_b_d.jpg"; 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    self.backgroundTask = [self.backgroundSession downloadTaskWithRequest:request]; 
    [self setDownloadButtonsAsEnabled:NO]; 
    self.imageView.hidden = YES; 
    // Start the download 
    [self.backgroundTask resume]; 
} 

- (NSURLSession *)backgroundSession 
{ 
    static NSURLSession *backgroundSession = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"]; 
     backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; 
    }); 
    return backgroundSession; 
} 

#pragma mark - NSURLSessionDownloadDelegate methods 
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite 
{ 
    double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     self.progressIndicator.hidden = NO; 
     self.progressIndicator.progress = currentProgress; 
    }); 
} 

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes 
{ 
    // Leave this for now 
} 

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 
{ 
    // We've successfully finished the download. Let's save the file 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 

    NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; 
    NSURL *documentsDirectory = URLs[0]; 

    NSURL *destinationPath = [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]]; 
    NSError *error; 

    // Make sure we overwrite anything that's already there 
    [fileManager removeItemAtURL:destinationPath error:NULL]; 
    BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error]; 

    if (success) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      UIImage *image = [UIImage imageWithContentsOfFile:[destinationPath path]]; 
      self.imageView.image = image; 
      self.imageView.contentMode = UIViewContentModeScaleAspectFill; 
      self.imageView.hidden = NO; 
     }); 
    } 
    else 
    { 
     NSLog(@"Couldn't copy the downloaded file"); 
    } 

    if(downloadTask == cancellableTask) { 
     cancellableTask = nil; 
    } else if (downloadTask == self.resumableTask) { 
     self.resumableTask = nil; 
     partialDownload = nil; 
    } else if (session == self.backgroundSession) { 
     self.backgroundTask = nil; 
     // Get hold of the app delegate 
     SCAppDelegate *appDelegate = (SCAppDelegate *)[[UIApplication sharedApplication] delegate]; 
     if(appDelegate.backgroundURLSessionCompletionHandler) { 
      // Need to copy the completion handler 
      void (^handler)() = appDelegate.backgroundURLSessionCompletionHandler; 
      appDelegate.backgroundURLSessionCompletionHandler = nil; 
      handler(); 
     } 
    } 

} 

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     self.progressIndicator.hidden = YES; 
     [self setDownloadButtonsAsEnabled:YES]; 
    }); 
} 
+2

Also ... was ist Ihre Frage? –

+0

Dieser Code funktioniert für einen einzigen Download, wenn ich drei Dateien herunterladen muss, wie werde ich verwalten .. ich nicht bekommen .. Bitte helfen Sie für mehrere Dateien. –

+0

Wenn Sie es für eine Datei tun können, welche Schwierigkeit haben Sie, diese auf weitere Downloads zu erweitern? – Abizern

Antwort

5

Sie mehr NSURLSessionDownloadTask die gleiche NSSession verwenden können und jeweils eine nach dem anderen auf dem gleichen mainQueue ausgeführt.

wenn erfolgreich heruntergeladen sie rufen:

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 

Wenn Sie einen MP4 100 MB und ein Bild von 10KB Download dann werden sie in verschiedenen Ordnungen in dieser Methode zurück.

So zu verfolgen, was Sitzung und was downloadTask in diesem

zurückgegeben hat man einen String-Kennung festlegen müssen, bevor Sie den Web-Service

rufen/Track NSURLSessions Zur Unterscheidung Sie

session.configuration.identifier 
gesetzt

zu unterscheiden NSURLSessionDownloadTask Verwendung

downloadTask_.taskDescription 

downloadTask_.taskDescription = [NSString stringWithFormat:@"%@",urlSessionConfigurationBACKGROUND_.identifier]; 

Zum Beispiel habe ich in meinem Projekt eine Reihe von Benutzer Lieblingsvideos und ihre Thumbnails heruntergeladen.

Jedes Element hatte eine ID eg1234567 So brauchte ich zwei Anrufe für jeden Lieblings

so erstellt i zwei Kennungen

"1234567_VIDEO" 
"1234567_IMAGE" 

rief dann zwei ws Anrufe zu tätigen und in der Kennung in der Sitzung übergeben .configuration.identifier

http://my.site/getvideo/1234567 
"1234567_VIDEO" 

http://my.site1/getimage/1234567 
"1234567_IMAGE" 

iOS7 die Einzelteile im Hintergrund herunterladen, app gehen zurückschlafen Wenngetan ruft

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 

ich dann

session.configuration.identifier 
"1234567_IMAGE" 

es aufgeteilt und überprüfen Sie die Werte

1234567_IMAGE 
"1234567" 
"_IMAGE" > item at location is a MP4 so save as /Documents/1234567.mp4 
"_VIDEO" > item at location is a jpg so save as /Documents/1234567.jpg 

Wenn Sie 3 Urls haben Sie anrufen Eine NSURLSessionDownloadTask pro NSSession haben kann

file 1 - NSSession1 > NSURLSessionDownloadTask1 
file 2 - NSSession2 > NSURLSessionDownloadTask2 
file 3 - NSSession3 > NSURLSessionDownloadTask3 

Dies scheint gut zu funktionieren, wenn die App im Vordergrund ist. Aber ich hatte Probleme bei der Verwendung von Hintergrundübertragung mit Hintergrundabfrage. Die erste NSSession> NSURLSessionDownloadTask1 würde zurückkehren und dann würde keiner der anderen aufgerufen werden.

So sicherer mehrere NSURLSessionDownloadTask in einem NSSession1

file 1 - NSSession1 > NSURLSessionDownloadTask1 
file 2 -   > NSURLSessionDownloadTask2 
file 3 -   > NSURLSessionDownloadTask3 

Seien Sie vorsichtig, wenn Sie dieses Anruf NSSession finishTasksAndInvalidate tun nicht invalidateAndCancel

//[session invalidateAndCancel]; 
    [session finishTasksAndInvalidate]; 

invalidateAndCancel die Sitzung stoppen und nicht die anderen Download-Aufgaben beenden

+0

Wie sagt Ihnen NSURLSession, wenn alle Dateien heruntergeladen sind, ohne dass die App im Hintergrund läuft? Die Delegate-Methode wird aufgerufen, wenn alle Download-Aufgaben abgeschlossen sind, aber nur, wenn ich meine App Hintergrund. Ich brauche es, wenn die App noch läuft. –

+0

@NYCTechEngineer Fügen Sie alle Aufgaben zu einem Array hinzu und verwenden Sie dann downloadsCompleted = (downloadTasks.indexOf ({$ 0.state == NSURLSessionTaskState.Running}) == nil)? wahr: falsch mit angeben, dass sie abgeschlossen sind. – DogCoffee

Verwandte Themen