我有一个继承的旧方法(responseForURL:error :),该方法写于15年。它使用一个URL并返回一个NSCachedURLResponse。该方法的工作方式是使用NSURLConnection进行Web服务调用。然后,它调用CFRunLoopRun()以便允许URL连接委托完成其数据的获取。一旦调用connectionDidFinishLoading:或connection:didFailWithError:委托方法,则将调用CFRunLoopStop(CFRunLoopGetCurrent)),从而允许responseForURL:error:方法继续运行并返回响应。换句话说,responseForURL:error:同步返回Web数据。该代码可以正常工作。
我使用NSURLSession更新了已弃用的NSURLConnect。此方法的功能与以前相同,但有一个例外:缩略图不再显示。
在调试前面的代码时,多次调用connection:didReceiveData :,直到完全下载了所有缩略图图像数据为止。 URLSession:dataTask:didReceiveData也被多次调用,像以前一样累积数据,但是缩略图为空白。我想了解的是为什么。
我不是使用CFRunLoopRun(),而是使用信号量来防止方法在检索到所有会话数据之前退出。
原始代码:
- (NSCachedURLResponse *)responseForURL:(NSURL*)url error:(NSError* __autoreleasing *)error {
NSParameterAssert(url);
__block NSCachedURLResponse *responseToReturn = nil;
dispatch_sync(_syncQueue, ^{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30];
NSCachedURLResponse *cachedResponse = [self->_diskCache cachedResponseForRequest:request];
if (cachedResponse) {
NSHTTPURLResponse *actualResponse = (NSHTTPURLResponse*)[cachedResponse response];
id etag = [[actualResponse allHeaderFields] objectForKey:@"Etag"];
[request setValue:etag forHTTPHeaderField:@"If-None-Match"];
}
self->_response = nil;
self->_error = nil;
self->_responseData = [NSMutableData new];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
CFRunLoopRun();
*error = self->_error;
if (cachedResponse && ![self->_responseData length]) {
responseToReturn = cachedResponse;
} else {
if (self->_response && self->_responseData) {
responseToReturn = [[NSCachedURLResponse alloc] initWithResponse:self->_response data:self->_responseData];
[self storeResponse:responseToReturn forRequest:request];
}
}
});
return responseToReturn;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
_response = (NSHTTPURLResponse*)response;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[_responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
_error = error;
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
CFRunLoopStop(CFRunLoopGetCurrent());
}
新代码:
- (NSCachedURLResponse *)responseForURL:(NSURL*)url error:(NSError* __autoreleasing *)error {
NSParameterAssert(url);
__block NSCachedURLResponse *responseToReturn = nil;
__weak typeof(self) weakSelf = self;
dispatch_sync(_syncQueue, ^{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30];
NSCachedURLResponse *cachedResponse = [weakSelf cachedResponseForRequest:request];
if (cachedResponse) {
NSHTTPURLResponse *actualResponse = (NSHTTPURLResponse *)[cachedResponse response];
id etag = [[actualResponse allHeaderFields] objectForKey:URLCacheETag];
[request setValue:etag forHTTPHeaderField:CCCURLCacheHTTPHeaderField];
}
weakSelf.semaphore = dispatch_semaphore_create(0);
weakSelf.response = nil;
weakSelf.responseData = [NSMutableData new];
weakSelf.error = nil;
NSURLSessionDataTask *dataTask = [weakSelf.session dataTaskWithRequest:request];
[dataTask resume];
dispatch_semaphore_wait(weakSelf.semaphore, DISPATCH_TIME_FOREVER);
*error = weakSelf.error;
if (cachedResponse && weakSelf.responseData.length == 0) {
// Get cached response data.
responseToReturn = cachedResponse;
} else {
if (weakSelf.response && weakSelf.responseData.length > 0) {
// We got response data. Cache it!
responseToReturn = [[NSCachedURLResponse alloc] initWithResponse:weakSelf.response data:weakSelf.responseData];
[weakSelf storeResponse:responseToReturn forRequest:request];
}
}
});
return responseToReturn;
}
- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
self->_response = (NSHTTPURLResponse*)response;
if (response) {
completionHandler(NSURLSessionResponseAllow);
} else {
completionHandler(NSURLSessionResponseCancel);
}
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
[_responseData appendData:data];
}
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error {
_error = error;
dispatch_semaphore_signal(_semaphore);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
_error = error;
dispatch_semaphore_signal(_semaphore);
}
应提取返回的响应数据并将其转换为缩略图。相反,缩略图为空白。