网络编程(GET, POST)
网络编程(GET, POST)
客户端展示网络数据的过程:
1.客户端发送请求给服务器端
2.服务器端收到请求,把数据(XML, JSON)传给客户端
3.客户端要对数据进行解析, 提取有用数据
4.然后在控件(label, tableView, imageView等等)上进行展示
客户端与服务器端进行沟通, 需要一定的规则(所谓的协议), 常用的协议:HTTP, 超文本传输协议
HTTP请求的方式
1.GET
2.POST
区别: 数据存放的位置不一样
GET请求数据存放在网址(URL)的后面, ?前是URL, ?后是参数, 参数以key=value的形式出现, 多个键值对用&连接
POST请求数据存放在请求体(HTTPBody)中
注:请求的格式可以看接口文档(API文档)
发出请求的方式:
1.同步请求, 发出请求后,必须等待服务器的回应, 才能继续执行
2.异步请求, 发出请求后, 无需等待服务器回应, 可以继续执行
同步GET请求
- (IBAction)get1:(id)sender {
NSURL, 网址类
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];
NSURLRequest, 请求类, 继承于NSObject
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection, 网络连接类, 继承于NSObject, 用于发出请求
//发出同步请求
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"response: %@ error: %@", response, error);
NSLog(@"%@", data);
将data转成NSString
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
XML解析
// NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
}
同步POST请求
- (IBAction)post1:(id)sender {
post请求的url后面没有参数
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"];
post请求的参数需要放在HTTPBody中, NSURLRequest不允许修改HTTPBody, 需要使用NSMutableURLRequest, 才能修改HTTPBody
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
请求体
NSString *value = @"type=focus-c";
request.HTTPBody = [value dataUsingEncoding:NSUTF8StringEncoding];
请求方式, 默认为@"GET"
request.HTTPMethod = @"POST";
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
[string release];
}
异步GET请求
- (IBAction)get2:(id)sender {
//1
NSString *string = @"http://image.zcool.com.cn/56/13/1308200901454.jpg";
URL中不能出现中文, 如果出现, 需要对字符串中的中文进行转码
NSString *rightString = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", rightString);
NSURL *url = [NSURL URLWithString: rightString];
//2
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3
异步请求需要创建connection, 并指定delegate, 当数据返回时, 会调用代理方法
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//开始连接
[connection start];
//释放
[connection release];
}
delegate方法
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"出现错误:%@", error);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"收到服务器的回应: %@", response);
self.mData = [NSMutableData dataWithCapacity:0];
}
服务器传数据给客户端, 会把数据拆分成多个数据包, 这个方法会执行多次, 每次收到一个数据包就执行一次, 并且应该把数据包都拼接在一起, 形成完整的数据
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"已经收到数据: %@", data);
[self.mData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"网络请求已经结束");
self.imageView.image = [UIImage imageWithData:self.mData];
}
异步POST请求
- (IBAction)post2:(id)sender {
//1
NSURL *url = [NSURL URLWithString:@"http://api.tudou.com/v3/gw"];
//2
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *valule = @"method=album.channel.get&appKey=myKey&format=json&channel=t&pageNo=1&pageSize=10";
request.HTTPBody = [valule dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = @"POST";
//3 发出异步请求
//3.1
// NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
// [connection start];
// [connection release];
//3.2
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
当请求结束才会执行block, 此时的data是一个完整的数据
NSLog(@"%@", response);
NSLog(@"%@", connectionError);
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
}];
}
点击imageView出现图片
- (IBAction)tap:(id)sender {
//1
NSURL *url = [NSURL URLWithString:@"http://image.zcool.com.cn/56/13/1308200901454.jpg"];
//2
NSURLRequest *requst = [NSURLRequest requestWithURL:url];
//3
NSData *data = [NSURLConnection sendSynchronousRequest:requst returningResponse:nil error:nil];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
//4. NSData转UIImage
UIImage *image = [UIImage imageWithData:data];
//5,在UIImageView上展示图片
self.imageView.image = image;
}
同步请求的缺点: 当数据比较大时, 由于需要等待服务器端把所有数据传过来, 如果网速比较慢, 就会造成应用程序"假死"状态(不能做其他操作, 必须等待数据全部传过来)
实现代码:
#import "NewsTableViewController.h"
#import "XHNews.h"
@interface NewsTableViewController ()
- (IBAction)refresh:(id)sender;
@property (nonatomic, retain) NSMutableArray *dataArray;
@end
@implementation NewsTableViewController
- (void)dealloc
{
[_dataArray release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"identifier1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:identifier] autorelease];
}
XHNews *news = [[XHNews alloc] init];
news = self.dataArray[indexPath.row];
cell.textLabel.text = news.title;
cell.detailTextLabel.text = news.desc;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:news.hot_pic]];
cell.imageView.image = [UIImage imageWithData:data];
return cell;
}
- (IBAction)refresh:(id)sender {
//异步GET请求
NSURL *url = [NSURL URLWithString:@"http://www.bjnews.com.cn/api/get_hotlist.php?page=1"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@", response);
NSLog(@"%@", connectionError);
//JSON解析
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@", dic);
//数据封装
self.dataArray = [NSMutableArray arrayWithCapacity:20];
for (NSDictionary *dictionary in dic[@"list"]) {
XHNews *news = [[XHNews alloc] init];
[news setValuesForKeysWithDictionary:dictionary];
[self.dataArray addObject:news];
[news release];
}
NSLog(@"%@", self.dataArray);
//展示数据(刷新tableView)
[self.tableView reloadData];
}];
}
@end
The one who wants to wear a crown must bear the weight!