URL Loading System Programming Guide-Using NSURLConnection

来源:互联网 发布:aics6破解软件 编辑:程序博客网 时间:2024/05/21 21:35

来源自:Using NSURLConnection

创建一个Connection

NSURLConnection对象有3种方式来获取URL的内容:同步,异步block回调和异步使用自定义的代理对象。

同步:使用sendSynchronousRequest:returningResponse:error:方法来执行HTTP请求。
使用block回调:如果不需要获取request的状态,仅仅是当数据完全收到后做一些操作,可以使用sendAsynchronousRequest:queue:completionHandler:方法。
使用代理:至少需要实现如下的方法connection:didReceiveResponse:, connection:didReceiveData:, connection:didFailWithError:connectionDidFinishLoading:。支持的代理方法定义在NSURLConnectionDelegate, NSURLConnectionDownloadDelegate, 和 NSURLConnectionDataDelegate 协议中。

Listing 2-1 中创建一个connection。创建了一个NSURLRequest一个实例,指定缓存策略和连接的超时时间。然后,创建一个NSURLConnection实例,指定请求和代理。如果NSURLConnection不能为请求创建连接,initWithRequest:delegate:返回nil。下面的代码片段也创建NSMutableData的实例来存储数据。

Listing 2-1 使用NSURLConnection创建连接

// Create the request.NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]                        cachePolicy:NSURLRequestUseProtocolCachePolicy                    timeoutInterval:60.0];// Create the NSMutableData to hold the received data.// receivedData is an instance variable declared elsewhere.receivedData = [NSMutableData dataWithCapacity: 0];// create the connection with the request// and start loading the dataNSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];if (!theConnection) {    // Release the receivedData object.    receivedData = nil;    // Inform the user that the connection failed.}

一收到initWithRequest:delegate:消息,传输就开始。在代理对象收到 connectionDidFinishLoading: 或者connection:didFailWithError:消息之前可以被取消掉,通过给connection 发送 cancel 消息。

当服务器已提供了足够的数据来创建一个NSURLResponse对象时,代理对象就会收到connection:didReceiveResponse:消息。代理方法可以通过检查NSURLResponse对象来获得数据预期的大小、MIME类型、建议的文件名和其他服务器提供的信息。

Listing 2-2 connection:didReceiveResponse: 的实现

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{    // This method is called when the server has determined that it    // has enough information to create the NSURLResponse object.    // It can be called multiple times, for example in the case of a    // redirect, so each time we reset the data.    // receivedData is an instance variable declared elsewhere.    [receivedData setLength:0];}

当收到数据时代理对象被发送connection:didReceiveData:消息。这个代理实现用来储存新收到的数据。

Listing 2-3 connection:didReceiveData: 的实现

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{    // Append the new data to receivedData.    // receivedData is an instance variable declared elsewhere.    [receivedData appendData:data];}

你也可以使用connection:didReceiveData:方法给用户提供一个连接进度指示器。首先在connection:didReceiveResponse:方法中,URL response对象调用expectedContentLength方法获取预期的长度。如果服务器未提供长度信息,expectedContentLength会返回NSURLResponseUnknownLength

如果在传输的过程中发生了错误,connection:didFailWithError:会被调用。传递的NSError对象参数会显示错误的细节。在user info字典中NSURLErrorFailingURLStringErrorKey键也提供了失败的URL。

Listing 2-4 connection:didFailWithError: 实现

- (void)connection:(NSURLConnection *)connection  didFailWithError:(NSError *)error{    // Release the connection and the data object    // by setting the properties (declared elsewhere)    // to nil.  Note that a real-world app usually    // requires the delegate to manage more than one    // connection at a time, so these lines would    // typically be replaced by code to iterate through    // whatever data structures you are using.    theConnection = nil;    receivedData = nil;    // inform the user    NSLog(@"Connection failed! Error - %@ %@",          [error localizedDescription],          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);}

最后,如果连接成功,调用connectionDidFinishLoading:方法。

Listing 2-5 connectionDidFinishLoading: 实现

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{    // do something with the data    // receivedData is declared as a property elsewhere    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);    // Release the connection and the data object    // by setting the properties (declared elsewhere)    // to nil.  Note that a real-world app usually    // requires the delegate to manage more than one    // connection at a time, so these lines would    // typically be replaced by code to iterate through    // whatever data structures you are using.    theConnection = nil;    receivedData = nil;}

实现一个POST请求

使用initWithRequest:delegate:方法创建 NSMutableURLRequest 对象.
需要构建body data,有三种情况:

  • 对于上传短的、内存中得数据,你应该对数据进行URL编码,见Continuing Without Credentials
  • 对于上传硬盘中的文件数据,调用setHTTPBodyStream:方法来告知NSMutableURLRequest从NSInputStream中读取数据,并把resulting data作为body content。
  • 对于大块构造数据,调用 CFStreamCreateBoundPair 来创建一对数据流,然后调用 setHTTPBodyStream: 告诉 NSMutableURLRequest使用其中某一个stream作为它的body content。

Listing 2-6 配置了一个NSMutableRequest 对象用于POST请求

// In body data for the 'application/x-www-form-urlencoded' content type,// form fields are separated by an ampersand. Note the absence of a// leading ampersand.NSString *bodyData = @"name=Jane+Doe&address=123+Main+St";NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com"]];// Set the request's content type to application/x-www-form-urlencoded[postRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];// Designate the request a POST request and specify its body data[postRequest setHTTPMethod:@"POST"];[postRequest setHTTPBody:[NSData dataWithBytes:[bodyData UTF8String] length:strlen([bodyData UTF8String])]];// Initialize the NSURLConnection and proceed as described in// Retrieving the Contents of a URL

使用setValue:forHTTPHeaderField:来给request指定不同的content type。
为了评估POST请求的进度,在代理方法中实现connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:方法。

0 0
原创粉丝点击