NSURLSession 學習筆記


最近學習了iOS7的一些新API,特別是NSURLSession着實強大方便很多。這里我參考了一些資料,作了個Demo。

https://github.com/cxjwin/TEST_URLSession.git

下面直接進入主題。

NSURLSession種類有三個:

1.Default sessions behave similarly to other Foundation methods for downloading URLs. They use a persistent disk-based cache and store credentials in the user’s keychain.

ps:Default sessions 和其他的網絡請求類似(和NSURLConnection類似),本地可以緩存文件。

2.Ephemeral sessions do not store any data to disk; all caches, credential stores, and so on are kept in RAM and tied to the session. Thus, when your app invalidates the session, they are purged automatically.

ps:Ephemeral sessions 不會存儲數據,這樣會節約內存,但是每次請求都會重新加在數據,所以適合數據量較少的請求(比如加載一段微博信息)。

3.Background sessions are similar to default sessions, except that a separate process handles all data transfers. Background sessions have some additional limitations, described in “Background Transfer Considerations.” 

ps:Background sessions default sessions類似,着重是后台下載或是上傳功能,這個也是NSURLSession強大的地方,在APP退到后台以后我們還可以繼續下載或是上傳,因為它由一個獨立的進程在管理(原話:the actual transfer is performed by a separate process),當任務完成后它會激活APP進程,通知任務狀態,然后你可以完成一些事情(比如保存下載的數據以便於用戶下次進入APP使用)。

NSURLSession 任務類型有三個:

1.Data tasks send and receive data using NSData objects. Data tasks are intended for short, often interactive requests from your app to a server. Data tasks can return data to your app one piece at a time after each piece of data is received, or all at once through a completion handler. Because data tasks do not store the data to a file, they are not supported in background sessions.

ps:Data tasks 主要是數據任務,它會在較短的時間內給予反饋(數據片段傳輸),你可以自己處理數據,也可以從completion handler獲取一個拼接好的數據。Data tasks不能用於Background sessions

2.Download tasks retrieve data in the form of a file, and support background downloads while the app is not running.

ps:Download tasks 會以文件的形式紀錄下數據,你可以對文件進行處理。個人覺得大數據適合這個任務,因為數據量比較,很有可能會涉及暫停、失敗、斷點續等等的行為。

3.Upload tasks send data (usually in the form of a file), and support background uploads while the app is not running.

這個跟Download tasks類似,因為不好模擬,Demo中沒有列舉這類tasks的用法。

下面是Demo講解:

這是后續可以用來暫存數據的字典

    self.tempDataDict = [NSMutableDictionary dictionary];    

這個是我們自定義的緩存文件夾

NSString *cachePath = @"TestCacheDirectory";

#ifdef DEBUG

    NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

    NSString *myPath = [myPathList objectAtIndex:0];

    NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];

    NSString *fullCachePath = [[myPath stringByAppendingPathComponent:bundleIdentifier] stringByAppendingPathComponent:cachePath];

    NSLog(@"Cache path: %@\n", fullCachePath);

#endif

    NSURLCache *myCache = 

    [[NSURLCache alloc] initWithMemoryCapacity:20 * kOneMegabyte diskCapacity:100 * kOneMegabyte diskPath:cachePath];

    

defaultSession會用到自己的緩存文件夾

    // defaultConfigObject

    // Default sessions behave similarly to other Foundation methods for downloading URLs. 

    // They use a persistent disk-based cache and store credentials in the user’s keychain.

    {

        NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];

        defaultConfigObject.timeoutIntervalForResource = kDefaultTimeoutIntervalForResource;

        defaultConfigObject.URLCache = myCache;

        defaultConfigObject.requestCachePolicy = NSURLRequestReturnCacheDataElseLoad;

        self.defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    }

    

ephemeralSession因為不會緩存文件,所以不需要設置,其實下載的時候它也會有一個臨時文件,但是下載完之后就被刪除了。

    // ephemeralConfigObject

    // Ephemeral sessions do not store any data to disk; all caches, credential stores, and so on are kept in RAM and tied to the session. 

    // Thus, when your app invalidates the session, they are purged automatically.

    {

        NSURLSessionConfiguration *ephemeralConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];

        ephemeralConfigObject.timeoutIntervalForResource = kDefaultTimeoutIntervalForResource;

        self.ephemeralSession = [NSURLSession sessionWithConfiguration:ephemeralConfigObject delegate:nil delegateQueue:[NSOperationQueue mainQueue]];

    }

    

backgroundSession這個不要設置超時限制,因為后台下載會根據你設備的負載程度決定分配給你用於下載的資源,很有可能半天不返回數據。

我測試過程有幾次設置超時限制為60秒,導致一直下載失敗,可能會是這個原因。

    // backgroundConfigObject

    // Background sessions are similar to default sessions, except that a separate process handles all data transfers. 

    // Background sessions have some additional limitations, described in “Background Transfer Considerations.”

    {

        NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration:kBackgroundSessionIdentifier];

        backgroundConfigObject.URLCache = myCache;

        backgroundConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;

        self.backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    }

方法講解:

使用block處理dataTask

因為不使用代理,所以中間的處理步驟都不會顯示,最后通過completionHandler返回數據,我們只要在completionHandler處理數據就行了,

因為background sessions不支持 dataTask所以沒法使用

- (void)dataTaskWithThreeSessionsWithBlock

{

    // data 會被存儲在URLCache里面

    // 如果URLCache里面有數據那么會被直接返回

    // 當使用block的時候,delegate不會觸發

    NSURLRequest *request1 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString1]];

    [[self.defaultSession dataTaskWithRequest:request1 completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"defaultSession data length : %lu", (unsigned long)[data length]);

    }] resume];

    

    // data 不會被存儲在URLCache里面

    // 每次都是重新下載

    NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString2]];

    [[self.ephemeralSession dataTaskWithRequest:request2 completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession data length : %lu", (unsigned long)[data length]);

    }] resume];

    

    // Because data tasks do not store the data to a file, they are not supported in background sessions.

    // 不支持backgroundSession

}

使用delegate處理dataTask

delegate處理dataTask可以自己實現一些細節

特別是在NSURLSessionDataDelegate里面我可以將 dataTask 轉化為 downloadTask(判斷請求數據大小),從而更靈活的使用

但是delegate需要自己處理對數據的保存

- (void)dataTaskWithThreeSessionsWithDelegate

{

    NSURLRequest *request1 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString1]];

    NSURLSessionDataTask *task1 = [self.defaultSession dataTaskWithRequest:request1];

    NSMutableData *tempData1 = [NSMutableData data];

    NSString *dataKey1 = [[NSNumber numberWithUnsignedInteger:task1.taskIdentifier + kDefaultSessionBaseIdentifier] stringValue];

    [self.tempDataDict setObject:tempData1 forKey:dataKey1];

    [task1 resume];

    

    // 這個不被緩存,完成時緩存delegate不會觸發

    // 所以推薦使用block獲取數據

    NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString2]];

    NSURLSessionDataTask *task2 = [self.ephemeralSession dataTaskWithRequest:request2];

    NSMutableData *tempData2 = [NSMutableData data];

    NSString *dataKey2 = [[NSNumber numberWithUnsignedInteger:task1.taskIdentifier + kEphemeralSessionBaseIdentifier] stringValue];

    [self.tempDataDict setObject:tempData2 forKey:dataKey2];

    [task2 resume];

    

    // Because data tasks do not store the data to a file, they are not supported in background sessions.

    // 不支持backgroundSession

}

下載任務都是異步的,很方便就實現異步下載

- (void)multiDataTasksWithDefaultSession

{

    [[self.defaultSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString1] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"defaultSession_1 : %lu", (unsigned long)[data length]);

    }] resume];

    

    [[self.defaultSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString2] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"defaultSession_2 : %lu", (unsigned long)[data length]);

    }] resume];

    

    [[self.defaultSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString3] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"defaultSession_3 : %lu", (unsigned long)[data length]);

    }] resume];

}

因為ephemeralSession不會存儲數據,所以處理數據量少的請求,需要即時更新的請求,比較合適

- (void)multiDataTasksWithEphemeralSession

{

    [[self.ephemeralSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString1] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession_1 : %lu", (unsigned long)[data length]);

    }] resume];

    

    [[self.ephemeralSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString2] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession_2 : %lu", (unsigned long)[data length]);

    }] resume];

    

    [[self.ephemeralSession dataTaskWithURL:[NSURL URLWithString:kTestImageURLString3] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession_3 : %lu", (unsigned long)[data length]);

    }] resume];

}

使用block處理downloadTask

這里面background sessions 不能使用 block

而且使用過程中我發現很多情況是delegateblock 只選其一

所以是視情況而定到底哪種適合

個人覺得對於下載來說還是delegate更為適合,因為下載一般時間比較長且用到background sessions的機會比較多

- (void)downloadTaskWithThreeSessionsWithBlock

{

    // tmp目錄,這兩個都沒有被存貯,下完就被刪除了,所以自己存一下文件

    NSURLRequest *request1 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString1]];

    [[self.defaultSession downloadTaskWithRequest:request1 completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"defaultSession : %@, %lu", location, (unsigned long)[[NSData dataWithContentsOfURL:location] length]);

        NSFileManager *fileManager = [NSFileManager defaultManager];

        NSString *cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];

        NSString *fileName = [location lastPathComponent];

        //[[[location lastPathComponent] stringByDeletingPathExtension] stringByAppendingPathExtension:@"jpeg"];

        NSString *cacheFile = [cacheDir stringByAppendingPathComponent:fileName];

        NSURL *cacheFileURL = [NSURL fileURLWithPath:cacheFile];

        

        NSError *_error = nil;

        if ([fileManager moveItemAtURL:location

                                 toURL:cacheFileURL

                                 error:&_error]) {

            /* Store some reference to the new URL */

        } else {

            /* Handle the error. */

            NSLog(@"error : %@", [_error localizedDescription]);

        }

    }] resume];

    

    NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString2]];

    [[self.ephemeralSession downloadTaskWithRequest:request2 completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession : %@, %lu", location, (unsigned long)[[NSData dataWithContentsOfURL:location] length]);

        NSFileManager *fileManager = [NSFileManager defaultManager];

        NSString *cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];

        NSString *fileName = [location lastPathComponent];

        //[[[location lastPathComponent] stringByDeletingPathExtension] stringByAppendingPathExtension:@"jpeg"];

        NSString *cacheFile = [cacheDir stringByAppendingPathComponent:fileName];

        NSURL *cacheFileURL = [NSURL fileURLWithPath:cacheFile];

        

        NSError *_error = nil;

        if ([fileManager moveItemAtURL:location

                                 toURL:cacheFileURL

                                 error:&_error]) {

            /* Store some reference to the new URL */

        } else {

            /* Handle the error. */

            NSLog(@"error : %@", [_error localizedDescription]);

        }

    }] resume];

    

    // !!! : Completion handler blocks are not supported in background sessions. Use a delegate instead.

}

使用delegate處理downloadTask,具體處理見Delegate方法

- (void)downloadTaskWithThreeSessionsWithDelegate

{

    NSURLRequest *request1 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString1]];

    [[self.defaultSession downloadTaskWithRequest:request1] resume];

    

    NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString2]];

    [[self.ephemeralSession downloadTaskWithRequest:request2] resume];

    

    NSURLRequest *request3 = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString3]];

    [[self.backgroundSession downloadTaskWithRequest:request3] resume];

}

backgroundSession使用delegate處理downloadTask,具體處理見Delegate方法

這個pdf還是比較大的,所以耐心等待一會,下載完成后對應的代理就會返回

- (void)downloadTaskWithBackgroundSessionWithDelegate

{

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestPdfURLString2]];

    NSURLSessionDownloadTask *downloadTask = 

    [self.backgroundSession downloadTaskWithRequest:request];

    [downloadTask resume];

}

判斷的規則可以自己定

// 當然如果如果數據比較大,你可以選擇將dataTask轉為downloadTask

// 這里我先判斷類型,時pdf的話就下載

- (void)changeDataTaskToDownloadTask

{

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestPdfURLString2]];

    NSURLSessionDataTask *dataTask = 

    [self.defaultSession dataTaskWithRequest:request];

    [dataTask resume];

}

這里我一直沒有找到比較好的辦法,查看是否所有的任務都完成了

所以我就用的最笨的方法,檢查剩余的任務量

downloadTasks count == 0 的時候那么所獲沒有可執行任務了,

這時候就說明所有的下載都已經完成,那么就做你該做的事情吧

- (void)multiDownloadTasksWithEphemeralSession

{    

    [[self.ephemeralSession downloadTaskWithURL:[NSURL URLWithString:kTestImageURLString1] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"1 : %@", location);

        

        

        [self.ephemeralSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

            NSLog(@"downloadTasks count : %d", [downloadTasks count]);

        }];

    }] resume];

    [[self.ephemeralSession downloadTaskWithURL:[NSURL URLWithString:kTestImageURLString2] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"2 : %@", location);

        

        

        [self.ephemeralSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

            NSLog(@"downloadTasks count : %d", [downloadTasks count]);

        }];

    }] resume];

    

    [[self.ephemeralSession downloadTaskWithURL:[NSURL URLWithString:kTestImageURLString3] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"3 : %@", location);

        

        

        [self.ephemeralSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

            NSLog(@"downloadTasks count : %d", [downloadTasks count]);

        }];

    }] resume];

}

對於相同的請求一般NSURLSession不會進行判斷的,所以需要自己判斷一下,同樣的請求會同時發送

當然有一些請求如果NSURLSession已經緩存了數據那么下次調用的時候 NSURLSession會直接取緩存里面的數據

不會再次向網絡請求,從而節約流量

這里就要視NSURLSession類型而定了

- (void)sameDownloadTasksWithDefaultSessionSeveralTime

{

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestImageURLString1]];

    

    NSURLSessionDownloadTask *task = [self.defaultSession downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession_1 : %@", location);

    }];

    [task resume];

    

    [self.defaultSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

        

        for (NSURLSessionDownloadTask *_task in downloadTasks) {

            if ([[[_task currentRequest] URL] isEqual:[NSURL URLWithString:kTestImageURLString1]]) {

                NSLog(@"same request....");

            }

        }

    }];

    

    [[self.defaultSession downloadTaskWithURL:[NSURL URLWithString:kTestImageURLString1] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSLog(@"ephemeralSession_2 : %@", location);

    }] resume];

}

后台下載完成后會觸發這個方法

執行一些自定義的處理后,調用appDelegate.completionHandler告訴APP已經處理完了

#pragma mark - 

#pragma mark - NSURLSessionDelegate

/* 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

{

    NSLog(@"%s, %d", __func__, __LINE__);

    AppDelegate *appDelegate = (id)[[UIApplication sharedApplication] delegate];

    BackgroundCompletionHandler handler = appDelegate.completionHandler;

    if (handler) {

        handler();

    }

}

typedef NS_ENUM(NSInteger, NSURLSessionResponseDisposition) {

    NSURLSessionResponseCancel = 0,                                 /* Cancel the load, this is the same as -[task cancel] */

    NSURLSessionResponseAllow = 1,                                  /* Allow the load to continue */

    NSURLSessionResponseBecomeDownload = 2,                         /* Turn this request into a download */

} NS_ENUM_AVAILABLE(10_9, 7_0);

這里我們可以選擇到底是 退出,轉下載,還是允許

#pragma mark - 

#pragma mark - NSURLSessionDataDelegate

/* The task has received a response and no further messages will be

 * received until the completion block is called. The disposition

 * allows you to cancel a request or to turn a data task into a

 * download task. This delegate message is optional - if you do not

 * implement it, you can get the response as a property of the task.

 */

- (void)URLSession:(NSURLSession *)session 

          dataTask:(NSURLSessionDataTask *)dataTask

didReceiveResponse:(NSURLResponse *)response

 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler

{

    NSLog(@"response MIMEType : %@.", response.MIMEType);

    if ([response.MIMEType rangeOfString:@"pdf"].length > 0) {// 如果是pdf的話,文件比較大那么轉為下載

        NSLog(@"MIMEType is a pdf, so become download");

        completionHandler(NSURLSessionResponseBecomeDownload);

    } else {

        completionHandler(NSURLSessionResponseAllow);

    }

}

dataTask已經轉為downloadTask

/* Notification that a data task has become a download task.  No

 * future messages will be sent to the data task.

 */

- (void)URLSession:(NSURLSession *)session 

          dataTask:(NSURLSessionDataTask *)dataTask

didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask

{

    NSLog(@"MIMEType is a pdf, has become download");

}

這里我們用字典分別對不同的URLSession進行數據存儲

delegate是需要我們自己存儲數據的

/* Sent when data is available for the delegate to consume.  It is

 * assumed that the delegate will retain and not copy the data.  As

 * the data may be discontiguous, you should use 

 * [NSData enumerateByteRangesUsingBlock:] to access it.

 */

- (void)URLSession:(NSURLSession *)session 

          dataTask:(NSURLSessionDataTask *)dataTask

    didReceiveData:(NSData *)data

{

    if (session == self.defaultSession) {

        NSString *dataKey = [[NSNumber numberWithUnsignedInteger:dataTask.taskIdentifier + kDefaultSessionBaseIdentifier] stringValue];

        NSMutableData *tempData = [self.tempDataDict objectForKey:dataKey];

        [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {

            [tempData appendBytes:bytes length:byteRange.length];

        }];

    } else if (session == self.ephemeralSession) {

        NSString *dataKey = [[NSNumber numberWithUnsignedInteger:dataTask.taskIdentifier + kEphemeralSessionBaseIdentifier] stringValue];

        NSMutableData *tempData = [self.tempDataDict objectForKey:dataKey];

        [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {

            [tempData appendBytes:bytes length:byteRange.length];

        }];

    }

}

ephemeralSession貌似不會觸發這個

所以用這個代理來預示是否已經緩存完數據不會很靠譜

/* Invoke the completion routine with a valid NSCachedURLResponse to

 * allow the resulting data to be cached, or pass nil to prevent

 * caching. Note that there is no guarantee that caching will be

 * attempted for a given resource, and you should not rely on this

 * message to receive the resource data.

 */

- (void)URLSession:(NSURLSession *)session 

          dataTask:(NSURLSessionDataTask *)dataTask

 willCacheResponse:(NSCachedURLResponse *)proposedResponse 

 completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler

{

    NSString *dataKey = nil;

    if (session == self.defaultSession) {

        dataKey = [[NSNumber numberWithUnsignedInteger:dataTask.taskIdentifier + kDefaultSessionBaseIdentifier] stringValue];

    } else if (session == self.ephemeralSession) {

        dataKey = [[NSNumber numberWithUnsignedInteger:dataTask.taskIdentifier + kEphemeralSessionBaseIdentifier] stringValue];

        

    }

    NSMutableData *tempData = [self.tempDataDict objectForKey:dataKey];

    NSLog(@"taskIdentifier : %@, data length : %lu", dataKey, (unsigned long)[tempData length]);

    NSLog(@"proposed response : %@", proposedResponse);

    if (proposedResponse) {

        completionHandler(proposedResponse);

    }

}

我們可以自己處理緩存的路徑

注釋掉的代碼是用默認的緩存文件夾緩存數據

#pragma mark - 

#pragma mark - NSURLSessionDownloadDelegate

- (void)URLSession:(NSURLSession *)session 

      downloadTask:(NSURLSessionDownloadTask *)downloadTask

didFinishDownloadingToURL:(NSURL *)location

{

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSString *cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];

    NSString *fileName = [location lastPathComponent];

    //[[[location lastPathComponent] stringByDeletingPathExtension] stringByAppendingPathExtension:@"jpeg"];

    NSString *cacheFile = [cacheDir stringByAppendingPathComponent:fileName];

    NSURL *cacheFileURL = [NSURL fileURLWithPath:cacheFile];

    

    NSError *error = nil;

    if ([fileManager moveItemAtURL:location

                             toURL:cacheFileURL

                             error:&error]) {

        /* Store some reference to the new URL */

    } else {

        /* Handle the error. */

        NSLog(@"error : %@", [error localizedDescription]);

    }

    

//    NSCachedURLResponse *cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:downloadTask.response data:[NSData dataWithContentsOfURL:location]];

//    [session.configuration.URLCache storeCachedResponse:cachedURLResponse forRequest:downloadTask.currentRequest];

    NSLog(@"Session %@ download task %@ finished downloading to URL %@\n", session, downloadTask, location);

}

這兩個代理顯示處理下載的進度

但是APP退到后台后就不會再觸發了

- (void)URLSession:(NSURLSession *)session 

      downloadTask:(NSURLSessionDownloadTask *)downloadTask

      didWriteData:(int64_t)bytesWritten

 totalBytesWritten:(int64_t)totalBytesWritten

totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

{

//    double p = (double)totalBytesWritten / totalBytesExpectedToWrite;

//    NSLog(@"downloadTask : %@, %.1f%%", downloadTask, p * 100.0);

}

- (void)URLSession:(NSURLSession *)session 

      downloadTask:(NSURLSessionDownloadTask *)downloadTask

 didResumeAtOffset:(int64_t)fileOffset

expectedTotalBytes:(int64_t)expectedTotalBytes

{

//    NSLog(@"Session %@ download task %@ resumed at offset %lld bytes out of an expected %lld bytes.\n",

//          session, downloadTask, fileOffset, expectedTotalBytes);

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM