NSURLConnection是蘋果提供的原生網(wǎng)絡訪問類。下面這段話來自Objc對它的理解。
iOS 7 和 Mac OS X 10.9 Mavericks 中一個顯著的變化就是對 Foundation URL 加載系統(tǒng)的徹底重構(gòu)。
NSURLConnection 作為 Core Foundation / CFNetwork 框架的 API 之上的一個抽象,在 2003 年,隨著第一版的 Safari 的發(fā)布就發(fā)布了。NSURLConnection 這個名字,實際上是指代的 Foundation 框架的 URL 加載系統(tǒng)中一系列有關聯(lián)的組件:NSURLRequest、NSURLResponse、NSURLProtocol、 NSURLCache、 NSHTTPCookieStorage、NSURLCredentialStorage 以及同名類 NSURLConnection。
NSURLRequest 被傳遞給 NSURLConnection。被委托對象(遵守以前的非正式協(xié)議 <NSURLConnectionDelegate> 和 <NSURLConnectionDataDelegate>)異步地返回一個 NSURLResponse 以及包含服務器返回信息的 NSData。
在一個請求被發(fā)送到服務器之前,系統(tǒng)會先查詢共享的緩存信息,然后根據(jù)策略(policy)以及可用性(availability)的不同,一個已經(jīng)被緩存的響應可能會被立即返回。如果沒有緩存的響應可用,則這個請求將根據(jù)我們指定的策略來緩存它的響應以便將來的請求可以使用。
在把請求發(fā)送給服務器的過程中,服務器可能會發(fā)出鑒權查詢(authentication challenge),這可以由共享的 cookie 或機密存儲(credential storage)來自動響應,或者由被委托對象來響應。發(fā)送中的請求也可以被注冊的 NSURLProtocol 對象所攔截,以便在必要的時候無縫地改變其加載行為。
不管怎樣,NSURLConnection 作為網(wǎng)絡基礎架構(gòu),已經(jīng)服務了成千上萬的 iOS 和 Mac OS 程序,并且做的還算相當不錯。但是這些年,一些用例——尤其是在 iPhone 和 iPad 上面——已經(jīng)對 NSURLConnection 的幾個核心概念提出了挑戰(zhàn),讓蘋果有理由對它進行重構(gòu)。
在 2013 的 WWDC 上,蘋果推出了 NSURLConnection 的繼任者:NSURLSession。
創(chuàng)建請求
NSURL *msgURL = [NSURL URLWithString:@"http://freezing-cloud-6077.herokuapp.com/messages.json"];
NSURLRequest *msgRequest = [NSURLRequest requestWithURL:msgURL cachePolicy:(NSURLRequestUseProtocolCachePolicy) timeoutInterval:60];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:msgRequest delegate:self];//默認自動開啟start
if (theConnection) {
NSMutableData *connData = [[NSMutableData alloc] init];
[self setConnectionData:connData];
}else {
NSLog(@"Connection failed...");
}
要接收來自網(wǎng)絡連接的數(shù)據(jù),需要實現(xiàn)以下代理方法。
// 收到服務器響應
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response {
[self.connectionData setLength:0];
}
// 將收到的數(shù)據(jù)附加到一個本地數(shù)據(jù)對象末尾
- (void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data {
[self.connectionData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
connection = nil;
self.connectionData = nil;
NSLog(@"Connection failed. Error - %@ %@",[error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *retString = [NSString stringWithUTF8String:[self.connectionData bytes]];
NSLog(@"json data: %@", retString);
NSError *parseError = nil;
NSArray *jsonArray =
[NSJSONSerialization JSONObjectWithData:self.connectionData
options:0
error:&parseError];
if (!parseError) {
NSLog(@"json array is %@", jsonArray);
} else {
NSString *err = [parseError localizedDescription];
NSLog(@"Encountered error parsing: %@", err);
}
connection = nil;
self.connectionData = nil;
}
發(fā)送請求
NSURLConnection默認發(fā)送異步請求,使用步驟大致是:
1.創(chuàng)建NSURL對象。
2.傳入NSURL創(chuàng)建一個NSURLRequest對象,設置請求頭和請求體。
3.使用NSURLConnection發(fā)送NSURLRequest。
發(fā)送請求分為同步請求和異步請求:
異步請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:messageBoardURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[request setHTTPMethod:@"POST"];//請求方法
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];//設置請求頭和請求體
[request setValue:[NSString stringWithFormat:@"%lu",
(unsigned long)[jsonData length]] forHTTPHeaderField:@"Content-Length"]; //3
[request setHTTPBody: jsonData];
//異步請求
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
}];
同步請求
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@""];
//2.創(chuàng)建一個請求對象(提供默認請求頭信息,默認GET請求)
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.把請求發(fā)送給服務器
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//4.解析服務器返回的信息
NSString *jsonData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
與RunLoop關系
設置代理:
1.[[NSURLConnection alloc]initWithRequest:request delegate:self];
默認自動發(fā)送請求。
2.NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
當startImmediately是NO的時候不會發(fā)生請求,需要手動調(diào)用[connect start];
線程:
默認情況下代理方法在主線程進行,也可以手動設置隊列
[connect setDelegateQueue:[[NSOperationQueue alloc]init]];
3.子線程中網(wǎng)絡請求
//創(chuàng)建OperationQueue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
.....
//此方法內(nèi)部會自動創(chuàng)建一個當前線程的runloop
[connection start];
//或者手動設置當前隊列
[connection setDelegateQueue:[[NSOperationQueue alloc]init]];
[[NSRunLoop currentRunLoop]run];
}];