异步请求不进入竣工块 [英] Async request does not enter completion block
问题描述
以下code是为了我更好地理解 [NSURLConnection的sendAsynchronousRequest:队列:completionHandler]。
有的NSLog
语句中的 completionHandler
块,但是当我在运行此main.m文件
在通过命令行项目X code,它永远不会进入 completionHandler
块。我已经使用了不同的队列, mainQueue
和 currentQueue
但既不工作尝试。
我的预感是,请求完成之前队列被释放,并保留周期是参与。
#进口<基金会/ Foundation.h>INT主(INT ARGC,为const char * argv的[]){
@autoreleasepool {
NSCache * myCache = [[NSCache的alloc]初始化]; NSArray的*图像= @
@http://i.stack.imgur.com/E66qr.png
@http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg
@\"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg\",
@的https://awestruckwanderer.files.word$p$pss.com/2014/02/alan-watts.png
@http://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg]; 对于(图像中的NSString *图片){
NSURL * myURL = [NSURL URLWithString:图片];
*的NSURLRequest请求= [[的NSURLRequest页头] initWithURL:myURL]; 的NSLog(@能处理的请求%@,@([NSURLConnection的canHandleRequest:请求]));
NSOperationQueue *队列= [[NSOperationQueue的alloc]初始化]; [NSURLConnection的sendAsynchronousRequest:要求
队列:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *响应,NSData的*数据,NSError *错误){
的NSLog(@在完成处理程序);
如果(!错误)
{
//保存数据和URL作为关键缓存
的NSLog(@图片添加到高速缓存);
[myCache的setObject:数据
forKey:myURL];
}其他
{
的NSLog(@图像不添加到缓存);
}
}];
}
}
返回0;
}
我的预感是,请求完成之前队列被释放,并保留周期涉及
块引用>不太。保留周期没有涉及。坚持是参与。您在
主
函数这样做。它退出的立即的 - 异步的东西(网络和随后的回调)是异步的,所以它会晚一点,的如果的,我们有过任何持久性。但是,我们不知道。主
退出,这意味着的整个该死的节目的被拆除, KABOOM 之前,有任何机会做任何网络,更不用说回调到网络后完成处理。现在的东西在现实生活中如何发生这种对比。在实际的iOS应用,
主
做的不的退出,因为它会调用UIApplicationMain
,其中循环,直到该应用程序将被终止。INT主(INT ARGC,CHAR *的argv [])
{
@autoreleasepool {
返回UIApplicationMain(ARGC,ARGV,零,
NSStringFromClass([AppDelegate类]));
}
}在这code,
UIApplicationMain
只是继续工作,直到它被中止或终止。同时,类和实例如雨后春笋般的生活,他们坚持,因为UIApplicationMain
不会停止。例如:@implementation MyViewController
- (无效){的someMethod
// ...
[NSURLConnection的sendAsynchronousRequest:要求
队列:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *响应,NSData的*数据,NSError *错误){
// ...
}
}
@结束现在,从某种意义上说,同样的事情发生了:
。的someMethod
立即退出。但是,我们的节目总体仍在运行!UIApplicationMain
有一个运行循环和运行的循环仍在循环。因此,事情生活,所以现在异步材料可能发生 - 我们可以通过网络,然后调用回调The following code is an attempt to me better understand
[NSURLConnection sendAsynchronousRequest:queue:completionHandler]
.There are
NSLog
statements in thecompletionHandler
block, but when I run this inmain.m
in XCode from a command line project, it never enters thecompletionHandler
blocks. I've tried using the different queues,mainQueue
andcurrentQueue
but neither work.My hunch is that the queue is being deallocated before the request is completed and that retain cycles are involved.
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSCache *myCache = [[NSCache alloc] init]; NSArray *images = @[ @"http://i.stack.imgur.com/E66qr.png", @"http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg", @"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg", @"https://awestruckwanderer.files.wordpress.com/2014/02/alan-watts.png", @"http://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg"]; for (NSString *image in images){ NSURL *myURL = [NSURL URLWithString:image]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myURL]; NSLog(@"Can handle request %@", @([NSURLConnection canHandleRequest:request])); NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { NSLog(@"In the completion handler"); if (!error) { // save data to cache with url as key NSLog(@"Image Added to Cache"); [myCache setObject:data forKey:myURL]; } else { NSLog(@"Image Not Added to Cache"); } }]; } } return 0; }
解决方案My hunch is that the queue is being deallocated before the request is completed and that retain cycles are involved
Not quite. Retain cycles are not involved. Persistence is involved. You are doing this in a
main
function. It exits immediately - the asynchronous stuff (the networking and the subsequent callback) is asynchronous, so it would come later, if we had any persistence. But we don't.main
exits, and that means that the whole darned program is torn down, kaboom, before there is any opportunity to do any networking, let alone call back into the completion handler after the networking.Now contrast this with how things happen in real life. In a real iOS app,
main
does not exit, because it callsUIApplicationMain
, which loops until the app is terminated.int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
In that code,
UIApplicationMain
just keeps running until it is aborted or otherwise terminated. Meanwhile, classes and instance have sprung to life, and they persist, becauseUIApplicationMain
does not stop. For example:@implementation MyViewController - (void) someMethod { // ... [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // ... } } @end
Now, in one sense, exactly the same thing happens:
someMethod
exits immediately. But our program overall is still running!UIApplicationMain
has a run loop and that run loop is still cycling. Thus, things live on, and so now the asynchronous material can happen - we can network and then call the callback.这篇关于异步请求不进入竣工块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!