簡體   English   中英

使用NSURLSession iOS在應用處於空閑狀態時下載圖像

[英]Downloading images when the app is in idle state usingNSURLSession iOS

我需要在應用程序處於空閑狀態時將一些大圖像下載到應用程序。我計划使用NSURLSession.Tutorials和可用的示例代碼使其完成,並確認可以進行后台下載。我的要求的最佳方法是,如果在下載未完成且只有幾個字節的情況下將應用程序從后台刪除,又會發生什么情況,我可以從停止的地方繼續下載嗎?同樣可以在iOS6中使用它嗎?我正在使用的委托方法。

- (NSURLSession *)backgroundSession
{
/*
 Using disptach_once here ensures that multiple background sessions with the same identifier are not created in this instance of the application. If you want to support multiple background sessions within a single process, you should create each session with its own identifier.
 */
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"];
        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return session;
}


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

    /*
     Report progress on the task.
     If you created more than one task, you might keep references to them and report on them individually.
     */

    if (downloadTask == self.downloadTask)
    {
        double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
        BLog(@"DownloadTask: %@ progress: %lf", downloadTask, progress);
        dispatch_async(dispatch_get_main_queue(), ^{
            self.progressView.progress = progress;
        });
    }
}


- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL
{
    BLog();

    /*
     The download completed, you need to copy the file at targetPath before the end of this block.
     As an example, copy the file to the Documents directory of your app.
    */
    NSFileManager *fileManager = [NSFileManager defaultManager];

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

    NSURL *originalURL = [[downloadTask originalRequest] URL];
    NSURL *destinationURL = [documentsDirectory URLByAppendingPathComponent:[originalURL lastPathComponent]];
    NSError *errorCopy;

    // For the purposes of testing, remove any esisting file at the destination.
    [fileManager removeItemAtURL:destinationURL error:NULL];
    BOOL success = [fileManager copyItemAtURL:downloadURL toURL:destinationURL error:&errorCopy];

    if (success)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImage *image = [UIImage imageWithContentsOfFile:[destinationURL path]];
            self.imageView.image = image;
            self.imageView.hidden = NO;
            self.progressView.hidden = YES;
        });
    }
    else
    {
        /*
         In the general case, what you might do in the event of failure depends on the error and the specifics of your application.
         */
        BLog(@"Error during the copy: %@", [errorCopy localizedDescription]);
    }
}


- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();

    if (error == nil)
    {
        NSLog(@"Task: %@ completed successfully", task);
    }
    else
    {
        NSLog(@"Task: %@ completed with error: %@", task, [error localizedDescription]);
    }

    double progress = (double)task.countOfBytesReceived / (double)task.countOfBytesExpectedToReceive;
    dispatch_async(dispatch_get_main_queue(), ^{
        self.progressView.progress = progress;
    });

    self.downloadTask = nil;
}


/*
 If an application has received an -application:handleEventsForBackgroundURLSession:completionHandler: message, the session delegate will receive this message to indicate that all messages previously enqueued for this session have been delivered. At this time it is safe to invoke the previously stored completion handler, or to begin any internal updates that will result in invoking the completion handler.
 */
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
    APLAppDelegate *appDelegate = (APLAppDelegate *)[[UIApplication sharedApplication] delegate];
    if (appDelegate.backgroundSessionCompletionHandler) {
        void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
        appDelegate.backgroundSessionCompletionHandler = nil;
        completionHandler();
    }

    NSLog(@"All tasks are finished");
}


-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    BLog();
}

ios7提供了NSURLSession API。

在某些情況下,在NSURLSession-n中恢復數據,您可以恢復已取消的下載或正在進行的下載。 為此,首先通過將NO傳遞給下載的setDeletesFileUponFailure:方法,以確保原始下載不會在失敗時刪除其數據。 如果原始下載失敗,則可以使用resumeData方法獲取其數據。 然后,您可以使用initWithResumeData:delegate:path:方法初始化新下載。 當下載恢復時,下載的委托會收到download:willResumeWithResponse:fromByte:消息。

僅當連接協議和要下載的文件的MIME類型都支持恢復時,才可以繼續下載。 您可以使用canResumeDownloadDecodedWithEncodingMIMEType:方法確定是否支持文件的MIME類型。

如果您在后台會話中安排下載,則當您的應用未運行時,下載將繼續。 如果您在標准或臨時會話中安排下載,則重新啟動應用程序時,下載必須重新開始。

在從服務器進行傳輸的過程中,如果用戶告訴您的應用程序暫停下載,則您的應用程序可以通過調用cancelByProducingResumeData:方法來取消任務。 稍后,您的應用程序可以將返回的恢復數據傳遞給downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:方法,以創建一個新的下載任務來繼續下載。

如果傳輸失敗,則使用NSError對象調用委托的URLSession:task:didCompleteWithError:方法。 如果任務是可恢復的,則該對象的userInfo字典包含NSURLSessionDownloadTaskResumeData鍵的值。 您的應用應使用可達性API確定何時重試,然后應調用downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:創建新的下載任務以繼續進行下載。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM