UITableView与JSON数据非常缓慢和冻结

时间:2014-11-09 12:28:14

标签: ios json xcode uitableview xcode6

早上好,

昨天我终于用我的数据库中的JSON解析数据制作了我的第一个TableViewController,但现在我遇到了一个问题:

  1. 该应用程序需要大约9-10秒才能加载并显示3个条目。
  2. 当我向下滚动TableView时,它会在显示新图像时冻结。
  3. 我会告诉你我的代码,因为我不知道为什么会这样,也许是因为图像非常大(它们是用iPhone相机制作的,并存储在我的FTP)。

    你知道为什么我的应用程序在加载结果然后通过它们导航时这么慢吗?

    viewDidLoad中:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [self fetchJson];
    }
    

    的TableView:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"carTableCell";
    
        CarTableViewCell *cell = [tableView
                                  dequeueReusableCellWithIdentifier:CellIdentifier];
    
        if (cell == nil) {
            cell = [[CarTableViewCell alloc]
                    initWithStyle:UITableViewCellStyleDefault
                    reuseIdentifier:CellIdentifier];
        }
    
        // Configure the cell...
        cell.makeLabel.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"id"];
        cell.likes.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"likes"];
        cell.comments.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"comments"];
        cell.username.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"username"];
        cell.refuser.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"user_ref"];
    
        cell.modelLabel.text = [[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"user"];
    
        NSURL * imageURL = [NSURL URLWithString:[[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"imagen"]];
        NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
        UIImage * carPhoto = [UIImage imageWithData:imageData];
    
        cell.carImage.image = carPhoto;
    
        NSURL * imageURL2 = [NSURL URLWithString:[[_jsonArray objectAtIndex:indexPath.row] valueForKey:@"image"]];
        NSData * imageData2 = [NSData dataWithContentsOfURL:imageURL2];
        UIImage * carPhoto2 = [UIImage imageWithData:imageData2];
    
        cell.profileImage.image = carPhoto2;
    
        return cell;
    }
    

    FetchJSON:

    -(void)fetchJson {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
    
            NSString * urlString = [NSString stringWithFormat:@"http://website.com/service.php"];
            NSURL * url = [NSURL URLWithString:urlString];
            NSData * data = [NSData dataWithContentsOfURL:url];
    
            self.carModels = [[NSMutableArray alloc] init];
            self.carMakes = [[NSMutableArray alloc] init];
            self.carImages = [[NSMutableArray alloc] init];
            self.likes = [[NSMutableArray alloc] init];
            self.comments = [[NSMutableArray alloc] init];
            @try
            {
                NSError *error;
                [_jsonArray removeAllObjects];
                _jsonArray = [NSJSONSerialization
                             JSONObjectWithData:data
                             options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
                             error:&error];
                for(int i=0;i<_jsonArray.count;i++)
                {
                    NSDictionary * jsonObject = [_jsonArray objectAtIndex:i];
                    NSString* imagen = [jsonObject objectForKey:@"imagen"];
                    [_carImages addObject:imagen];
    
                    NSDictionary * jsonObject2 = [_jsonArray objectAtIndex:i];
                    NSString* user = [jsonObject2 objectForKey:@"user"];
                    [_carMakes addObject:user];
    
                    NSDictionary * jsonObject3 = [_jsonArray objectAtIndex:i];
                    NSString* date = [jsonObject3 objectForKey:@"date"];
                    [_carModels addObject:date];
                }
            }
            @catch (NSException * e)
            {
                NSLog(@"Exception: %@", e);
            }
            @finally
            {
                [self.tableView reloadData];
            }
        }
        );
    }
    

    那是我的JSON输出文件:

    [{"id":"15","user":"1","imagen":"http:\/\/website.com\/juliaroberts.jpg","date":"2014-09-13","userID":"1","image":"http:\/\/m.c.lnkd.licdn.com\/mpr\/mpr\/shrink_200_200\/p\/3\/000\/25b\/1fe\/200e9f3.jpg","username":"*jordi","id_post":"15","likes":"5","comments":"2","post_id":"15","user_ref":"*juliaroberts"},{"id":"16","user":"1","imagen":"http:\/\/website.com\/onedirection.png","date":"2014-11-11","userID":"1","image":"http:\/\/m.c.lnkd.licdn.com\/mpr\/mpr\/shrink_200_200\/p\/3\/000\/25b\/1fe\/200e9f3.jpg","username":"*jordi","id_post":"16","likes":"1","comments":"0","post_id":"16","user_ref":"*onedirection"},{"id":"17","user":"1","imagen":"http:\/\/website.com\/onedirection.png","date":"2014-11-09","userID":"1","image":"http:\/\/m.c.lnkd.licdn.com\/mpr\/mpr\/shrink_200_200\/p\/3\/000\/25b\/1fe\/200e9f3.jpg","username":"*jordi","id_post":"17","likes":"3","comments":"3","post_id":"17","user_ref":"*onedirection"}]
    

    提前致谢。

2 个答案:

答案 0 :(得分:1)

问题是您的图像是同步下载的,并且会阻塞主线程。因此,每次看到tableview单元格时,都会下载图像。

这是最昂贵的代码:

  NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
  UIImage * carPhoto = [UIImage imageWithData:imageData];

您应该始终避免在与UI运行(主线程)相同的线程上运行繁重的操作。

您的解决方法是: 1)。将下载代码的任何图像移动到后台线程。 2)。将下载的UIImage返回到主线程以在UI中显示。 3)。下载后缓存图像以节省流量。

基本上,您可以使用大量第三方库来完成这些任务。最受欢迎的是SDWebImage: https://github.com/rs/SDWebImage

答案 1 :(得分:0)

您应该尝试使用Instruments来衡量应用的效果瓶颈。阅读raywenderlich.com上的这篇文章简单介绍了这类问题的分析。

完全基于您发布的代码,看起来您正在为主线程中的汽车获取图像,从而导致性能提升。执行此操作的代码行是:

NSData * imageData = [NSData dataWithContentsOfURL:imageURL];

原因是dataWithContentsOfURL在当前线程中同步运行,在本例中是主线程。 dataWithContentsOfURL的{​​{3}}会对此进行确认,并建议改为使用Apple Documentation