#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]] delegate:self];
// 决定代理方法在哪个队列中执行(在子线程中执行)
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"didReceiveResponse----%@", [NSThread currentThread]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(@"didReceiveData----%@", [NSThread currentThread]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"connectionDidFinishLoading----%@", [NSThread currentThread]);
}
@end
上面这段程序是在主线程
中创建NSURLConnection ,给服务器发送请求,程序可以成功的接受到服务器返回的数据
但是一但将请求放在子线程
中发送,就不能接受到服务器返回的数据了。情况如下面代码所示:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]] delegate:self];
// 决定代理方法在哪个队列中执行(在子线程中执行)
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
});
}
这是为什么呢,原因如下:
- 因为
NSURLConnection
跟RunLoop
有关系 NSURLConnection
发出请求,等待接收服务器一点一点返回的数据,需要有一个运行循环等待服务器给NSURLConnection
数据,也就是说NSURLConnection
是在RunLoop
中接收服务器返回的数据NSURLConnection
内部会关联当前线程对应的RunLoop
,不断的给当前线程的RunLoop
传递消息,RunLoop
接收到Source
进行处理NSURLConnection
在子线程发送请求时,子线程的RunLoop
默认是不启动的,所以接受不到服务器返回的数据。在主线程中,主线程的RunLoop
是默认启动的,所以可以接受服务器返回的数据- 要想
NSURLConnection
在子线程发送请求,可以接收到服务器返回的数据,要开启子线程的RunLoop
,具体方法如下,有两种方法实现:
- 方法一:
#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]] delegate:self];
// 决定代理方法在哪个队列中执行
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
// 启动子线程的runLoop
[[NSRunLoop currentRunLoop] run];
});
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"didReceiveResponse----%@", [NSThread currentThread]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(@"didReceiveData----%@", [NSThread currentThread]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"connectionDidFinishLoading----%@", [NSThread currentThread]);
}
@end
- 方法二:
#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
/** runLoop */
@property (nonatomic, assign) CFRunLoopRef runLoop;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]] delegate:self];
// 决定代理方法在哪个队列中执行
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
// 启动子线程的runLoop
self.runLoop = CFRunLoopGetCurrent();
// 启动runLoop
CFRunLoopRun();
});
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"didReceiveResponse----%@", [NSThread currentThread]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(@"didReceiveData----%@", [NSThread currentThread]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"connectionDidFinishLoading----%@", [NSThread currentThread]);
// 一般来说RunLoop会自己停止,然是如果RunLoop没有自动停止,我们可以手动停止
// CFRunLoopStop(self.runLoop);
}
@end