#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