在UITableView中仅加载可见单元格

时间:2014-10-14 04:11:27

标签: ios objective-c uitableview

所以我有一个应用程序从数据库中读取记录,并基本上用DB中的信息填充UITableView。一些信息包括一个图像,它从我有的在线服务器带来。一切正常,但程序有点慢,滚动有点滞后/跳跃,因为它一次带来所有图像,而不是在我滚动时带它们。有没有办法改变它,以便当我滚动它带来下几个可见的记录?

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {

    static NSString *CellIdentifier = @"VersionCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                      reuseIdentifier:CellIdentifier];
    }

    STSneakerInfo *info = [_versionInfo objectAtIndex:indexPath.row];

    cell.textLabel.font = [UIFont boldSystemFontOfSize:14.1];
    [[cell textLabel] setNumberOfLines:2];

    cell.textLabel.text = [[_uniqueBrand stringByAppendingString:@" "] stringByAppendingString: info.version];

    cell.detailTextLabel.textColor = [UIColor grayColor];
    cell.detailTextLabel.font = [UIFont boldSystemFontOfSize:14.1];
    cell.detailTextLabel.text = info.initialReleaseDate;

    NSString *brandVersion = [[_uniqueBrand stringByAppendingString:@" "] stringByAppendingString:info.version];
    NSString *underscoredBrandVersion = [brandVersion stringByReplacingOccurrencesOfString:@" " withString:@"_"];
    NSString *underscoredBrandName = [_uniqueBrand stringByReplacingOccurrencesOfString:@" " withString:@"_"];

    NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: ([[[[[@"http://www.abc/img/" stringByAppendingString:underscoredBrandName] stringByAppendingString:@"/"] stringByAppendingString:underscoredBrandVersion] stringByAppendingString:@"/"] stringByAppendingString:@"default.jpg"])]];
    cell.imageView.image = [UIImage imageWithData: imageData];

    return cell;
}

4 个答案:

答案 0 :(得分:2)

UITableView类永远不会加载单元格,直到它们即将出现在屏幕上。 我建议你使用GCD下载图像背景。完成后,注意UI改变。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       //Download images
        dispatch_async(dispatch_get_main_queue(), ^{
            //Notice UI to change
        });
});

答案 1 :(得分:2)

您可以使用(https://github.com/rs/SDWebImage)下载图像异步。它简单快捷。

我更喜欢这个库,因为它会处理你的缓存。 只需写下面的代码

[cell.imageView sd_setImageWithURL: [NSURL URLWithString: ([[[[[@"http://www.abc/img/" stringByAppendingString:underscoredBrandName] stringByAppendingString:@"/"] stringByAppendingString:underscoredBrandVersion] stringByAppendingString:@"/"] stringByAppendingString:@"default.jpg"])]];

你也可以按照wenchenHuang上面的回答下载后台线程中的图片。使用下面的代码。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString: ([[[[[@"http://www.abc/img/" stringByAppendingString:underscoredBrandName] stringByAppendingString:@"/"] stringByAppendingString:underscoredBrandVersion] stringByAppendingString:@"/"] stringByAppendingString:@"default.jpg"])];
        if (data)
        {
            UIImage *img = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (img)
                    cell.imageView.image = img;
            });
        }

    });

也许这会对你有帮助。

答案 2 :(得分:1)

以下是DLImageLoader

的完整实际示例

https://github.com/AndreyLunevich/DLImageLoader-iOS/tree/master/DLImageLoader

DLImageLoader非常精心编写,不断维护,超轻量级,并且可以正确处理略读

很难被击败,并且在许多用户中使用过很多用途。

它实际上是一个维护得非常好的库 - 最重要的是,新的Swift版本是Swift编程中的巅峰之作,它是如何实现它的模型。

PFObject *aFacebookUser = [self.fbFriends objectAtIndex:thisRow];
NSString *facebookImageURL = [NSString stringWithFormat:
    @"http://graph.facebook.com/%@/picture?type=large",
    [aFacebookUser objectForKey:@"id"] ];

__weak UIImageView *loadMe = self.cellImage;
[DLImageLoader loadImageFromURL:facebookImageURL
   completed:^(NSError *error, NSData *imgData)
    {
    if ( loadMe == nil ) return;

    if (error == nil)
        {
        UIImage *image = [UIImage imageWithData:imgData];
        image = [image ourImageScaler];
        loadMe.image = image;
        }
    else
        {
        // an error when loading the image from the net
        }
    }];

另一个现实世界的例子,

-(UICollectionViewCell *)collectionView:(UICollectionView *)cv
         cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    NSInteger thisRow = indexPath.row;
    BooksCell *cell;
    cell = [cv dequeueReusableCellWithReuseIdentifier:
              @"CellBooksNormal" forIndexPath:indexPath];

    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

    // set text items...
    cell.title = @"blah;

    // set image items using DLImageLoader...

    __weak UIBookView *loadMe = cell.anImage;
    [DLImageLoader loadImageFromURL:imUrl
       completed:^(NSError *error, NSData *imgData)
        {
        [loadMe use:[UIImage imageWithData:imgData]];
        }];

    return cell;
    }

答案 3 :(得分:0)

滚动缓慢的原因是您正在主线程上下载图像。

NSData *imageData = [[NSData alloc] initWithContentsOfURL:

在主线程上运行的那段代码将进行网络调用并开始从服务器下载内容。执行停止,直到完成。这意味着你不能再向下滚动,直到图像被加载。

这有很多变通方法。然而,所有人的逻辑都是一样的。在单独的线程中下载图像并在完成后加载它。

如果您在项目中使用AFNetworking,则可以在setImageWithURL:对象上使用UIImageView。您需要包含UIImageView+AFNetworking.h。它有一个内置的缓存机制,它将缓存为该会话下载的图像。