首页 > 代码库 > ios网络学习------6 json格式数据的请求处理

ios网络学习------6 json格式数据的请求处理

#import "MainViewController.h"
#import "Video.h"

#define kBaseURL @"http://192.168.3.252/~apple"

@interface MainViewController ()<UITableViewDataSource, UITableViewDelegate>
@property (strong, nonatomic) NSArray *dataList;
@property (weak, nonatomic) UITableView *tableView;
@end

@implementation MainViewController
</pre><p class="p1">/*</p><p class="p2"><span class="s1"> </span>在网络应用开发中,</p><p class="p2"><span class="s1"> 1 </span>数据是同步加载的,可以保证用户有的看</p><p class="p2"><span class="s1"> 2 </span>图像,音频,视频是异步加载的。可以保证在不阻塞主线程的使用的前提下,用户可以渐渐的看到多媒体信息。</p><p class="p1"> */</p><pre code_snippet_id="412158" snippet_file_name="blog_20140630_1_3481337" name="code" class="objc">
#pragma mark 实例化视图
- (void)loadView
{
    self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
    //1 tableview
    CGRect frame = self.view.bounds;
    UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height - 44) style:UITableViewStylePlain];
    //1)数据源
    [tableView setDataSource:self];
    //2)代理
    [tableView setDelegate:self];
    //)设置表格高度
    [tableView setRowHeight:80];
    [self.view addSubview:tableView];
    self.tableView = tableView;
    
    //toolBar
    UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, tableView.bounds.size.height, 320, 44)];
    [self.view addSubview:toolBar];
    
    //添加toolbar按钮
    UIBarButtonItem *item1 = [[UIBarButtonItem alloc]initWithTitle:@"load json" style:UIBarButtonItemStyleDone target:self action:@selector(loadJson)];
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc]initWithTitle:@"load xml" style:UIBarButtonItemStyleDone target:self action:@selector(loadXML)];
    UIBarButtonItem *item3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolBar setItems:@[item3, item1, item3, item2, item3]];
}

#pragma mark -uitableview数据源方法  对于uitableview下面这两个方法是必须实现的。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataList.count;
}

//每填充一行都调用一次这个方法。知道界面上的所有行都填充完毕。,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //使用可充用标示符查询可重用单元格
    static NSString *ID = @"MyCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    //设置单元格内容
    Video *v = self.dataList[indexPath.row];
    
    cell.textLabel.text = v.name;
    cell.detailTextLabel.text = v.teacher;
    //加载图片
    //1)同步加载网络图片,同步方法以为这这些指令在完成之前,后续指令都无法执行。
    //注意:在开发网络应用时,不要使用同步方法加载图片,否则会严重影响用户体验
//    NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL];
//    NSURL *imageUrl = [NSURL URLWithString:imagePath];
//    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
//    UIImage *image = [UIImage imageWithData:imageData];
//    
//    //2)异步加载网络图片
//    //网络连接本身就有异步命令 sendAsync
//    [cell.imageView setImage:image];
    //如果缓存图像不存在
    if (v.cacheImage == nil) {
        //使用默认图像占位,即能够保证有图像,又能够保证有地方。
        UIImage *image = [UIImage imageNamed:@"user_default.png"];
        [cell.imageView setImage:image]; //使用默认图像占位
        //开启异步连接,加载图像,因为加载完成之后,需要刷新对应的表格航
        [self loadImageAsyncWithIndexPath:indexPath];
    }else
    {
        [cell.imageView setImage:v.cacheImage];
    }
    
    //[self loadImageAsyncWithUrl:imageUrl imageView:cell.imageView];
    return cell;
}


#pragma mark 异步加载网络图片
//由于uitableview是可重用的,为了避免用户快速频繁刷新表格,造成数据冲突,不能直接将uiimageview传入异步方法
//正确的解决方法是:将表格行的indexpath传入异步方法,加载完成图像以后,直接刷新指定的行。
- (void)loadImageAsyncWithIndexPath:(NSIndexPath *)indexPath
{
    Video *v = self.dataList[indexPath.row]; //取出当前要填充的行
    NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL];
    NSURL *imageUrl = [NSURL URLWithString:imagePath];
    
    //NSLog(@"%@ %@", url, imageView);
    //1 request
    NSURLRequest *request = [NSURLRequest requestWithURL:imageUrl];
    //2 connection sendasync异步请求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        //UIImage *image = [UIImage imageWithData:data];
        //[imageView setImage:image];
        //将网络数据保存至缓存图像。
        v.cacheImage = [UIImage imageWithData:data];
        //刷新表格
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
    }];
}

#pragma mark 处理json数据
- (void)handlerJSONData:(NSData *)data
{
    //json文件中的[]表示一个数据。
    //反序列化json数据
    /*
     序列化: 将一个nsboject转换成序列数据,以便通过互联网进行传输。
     反序列化:将网络上获取的数据反向生成我们需要的对象。
     */
    //第二个参数是解析方式,一般用NSJSONReadingAllowFragments
    NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    
    NSLog(@"%@", array);  //json解析以后是nsarray格式的数据。
    
    //提示:如果开发网络应用,可以将反序列化出来的对象,保存至沙箱,以便后续开发使用。
    NSArray *docs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [docs[0]stringByAppendingPathComponent:@"json.plist"];
    [array writeToFile:path atomically:YES]; //把array里面的数据写入沙箱中的jspn.plist中。
    
    //给数据列表赋值
    NSMutableArray *arrayM = [NSMutableArray array];
    for (NSDictionary *dict in array) {
        Video *video = [[Video alloc]init];
        //给video赋值
        [video setValuesForKeysWithDictionary:dict];
        [arrayM addObject:video];
    }
    self.dataList = arrayM;
    //刷新表格
    [self.tableView reloadData];
    
    NSLog(@"%@", arrayM);  //这句话将调用video里面的description和nsarray+log里面的descriptionWithLocale
}

#pragma mark 加载json
- (void)loadJson
{
    NSLog(@"load json");
    //从web服务器加载数据
    NSString *str = @"http://www.baidu.com?format=json";  //这里是乱写的
    //提示:NSData本身具有同步方法,但是在实际开发中,不要使用次方法
    //在使用NSData的同步方法时,无法指定超时时间,如果服务器连接不正常,会影响用户体验。
    //NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
    //简历NSURL
    NSURL *url = [NSURL URLWithString:str];
    //建立NSURLRequest
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f];
    //建立NSURLConnect的同步方法加载数据
    NSURLResponse *response = nil;
    NSError *error = nil;
    //同步加载数据
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    //错误处理
    if (data != nil) {
        //下面这两句话本身没有什么意义,仅用于跟踪调试。
        NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@", result);
        
        //在处理网络数据的时候,不要将NSData转换成nsstring。
        [self handlerJSONData:data];
    }else if (data == nil && error == nil){
        NSLog(@"空数据");
    }else
    {
        NSLog(@"%@", error.localizedDescription);
    }
}
#pragma mark 加载xml
- (void)loadXML
{
    NSLog(@"load xml");
}
//- (void)viewDidLoad
//{
//    [super viewDidLoad];
//}

@end