2014-03-13 105 views
6

我正在使用'AFNetworking', '2.0.0'下載數據。AFNetworking 2.0.0在後臺下載

我需要下載大文件。當用戶鎖定屏幕或按Home鍵時,應該暫停(或繼續在後臺下載),如果我返回到應用程序,它應該恢復。

此外我需要顯示下載的進度。

我搜索了很多例子,但是沒有找到任何東西'AFNetworking', '2.0.0'

我爲iOS 6.0+版本創建應用程序,因此我無法使用AFHTTPSessionManagerAFURLSessionManager

+0

也許你可以在這裏找到解決方案:http://stackoverflow.com/questions/12563753/afnetworking-not-resuming-download – Weizhi

回答

1

當你的應用程序切換到後臺暫停/停止下載操作,並配備在前臺時恢復中的NSOperation隊列已暫停下載操作。 閱讀這些代碼可以幫助你:

 AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:filePath shouldResume:YES]; 




     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
      //handel completion 
      [operations removeObjectForKey:audioItem.filename]; 

     }failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
      //handel failure 
        operation = [operations objectForKey:audioItem.filename]; 
        [operation cancel]; 
        [operations removeObjectForKey:audioItem.filename]; 
        if (error.code != NSURLErrorCancelled) { 
         [self showErrorAlert]; 
         NSLog(@"Error: %@", error); 
        } 




     }]; 


    [operation setProgressiveDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) { 
      //handel progress 
      NSNumber *progress = [NSNumber numberWithFloat:((float)totalBytesReadForFile/(float)totalBytesExpectedToReadForFile)]; 
      float progress=progress.floatValue; 
      [self performSelectorOnMainThread:@selector(updateProgressBar:) withObject:[NSArray arrayWithObjects:audioItem, progress, nil] waitUntilDone: YES]; 

     }]; 

     [operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{ 
      // TODO: Clean up operations 
      NSLog(@"App has been in background too long, need to clean up any connections!"); 
     }]; 

     [operations setValue:operation forKey:@"key"]; // store the NSOperation for further use in application to track its status. 
     [downloadQueue addOperation:operation];//here downloadQueue is NSOperationQueue instance that manages NSOperations. 

要暫停下載操作使用本:

[operation pause]; 

要繼續使用該行的類別:

[operation resume]; 
+0

什麼是'操作'? – Siriss

+0

「操作」在這裏是NSMutableDictionary,將文件名存儲爲鍵並將NSOperation對象存儲爲值。 –

3

對於後臺下載在iOS 7或更高版本上,我使用NSURLSessionNSURLSessionDownloadTask。在ProjectNavigator-> YourProject-> YourTarget->功能上BackgroundMode

開關(標籤) - >背景模式 enter image description here

加入您的AppDelegate方法- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptionsNSURLSessin與下一個代碼的初始化劑:

NSURLSessionConfiguration *sessionConfiguration; 
    NSString *someUniqieIdentifierForSession = @"com.etbook.background.DownloadManager"; 
    if ([[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] firstObject] integerValue] >= 8) { 
//This code for iOS 8 and greater 
     sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:someUniqieIdentifierForSession]; 
    } else { 
this code for iOS 7 
     sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:someUniqieIdentifierForSession]; 
    } 
    sessionConfiguration.HTTPMaximumConnectionsPerHost = 5; 
    self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration 
               delegate:self 
              delegateQueue:[NSOperationQueue mainQueue]]; 

當然,不要忘了申報session屬性搭配:

@property (nonatomic, strong) NSURLSession session; 

另外補充完成處理特性(它會需要,如果你想申請終止或崩潰後獲得後臺下載程序的回調):

@property (nonatomic, copy) void(^backgroundTransferCompletionHandler)(); 

添加委託方法中的AppDelegate:

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

    NSError *error; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 

    NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent; 
    NSURL *destinationURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:destinationFilename]; 

    if ([fileManager fileExistsAtPath:[destinationURL path]]) { 
     [fileManager removeItemAtURL:destinationURL error:nil]; 
    } 
    [fileManager copyItemAtURL:location 
         toURL:destinationURL 
         error:&error]; 
} 

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ 
    if (error != nil) { 
     NSLog(@"Download completed with error: %@", [error localizedDescription]); 
    } 
    else{ 
     NSLog(@"Download finished successfully."); 
} 

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ 

    if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) { 
     NSLog(@"Unknown transfer size"); 
    } 
    else{ 
     NSLog(@"progress = %lld Mb of %lld Mb", totalBytesWritten/1024/1024, totalBytesExpectedToWrite/1024/1024); 
    } 
} 

-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{ 
    ETBAppDelegate *appDelegate = [UIApplication sharedApplication].delegate; 

    // Check if all download tasks have been finished. 
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 

     if ([downloadTasks count] == 0) { 
      if (appDelegate.backgroundTransferCompletionHandler != nil) { 
       // Copy locally the completion handler. 
       void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler; 

       // Make nil the backgroundTransferCompletionHandler. 
       appDelegate.backgroundTransferCompletionHandler = nil; 

       [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
        // Call the completion handler to tell the system that there are no other background transfers. 
        completionHandler(); 

        // Show a local notification when all downloads are over. 
        UILocalNotification *localNotification = [[UILocalNotification alloc] init]; 
        localNotification.alertBody = @"All files have been downloaded!"; 
        [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; 
       }]; 
      } 
     } 
    }]; 
} 


//Background download support (THIS IMPORTANT METHOD APPLICABLE ONLY IN YOUR AppDelegate.m FILE!!!) 
-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{ 
    self.backgroundTransferCompletionHandler = completionHandler; 
} 

並聲明你的類(在AppDelegate中。在我的例子.h文件)符合協議NSURLSessionDelegate喜歡這裏:

NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:[NSURL URLWithString:urlString]]; 
task.taskDescription = [NSString stringWithFormat:@"Downloading file %@", [urlString lastPathComponent]]; 
[task resume]; 

所以,當你的應用程序結束後開始,您的會話將被恢復並委託方法:

@interface AppDelegate : UIResponder <UIApplicationDelegate, NSURLSessionDelegate> 

然後再添加下載任務將被解僱。此外,如果您的應用程序將從後臺喚醒到前臺,您的應用程序委託方法也會被觸發。