UITableViewCells 中的图像加载错误

2023-11-27

我正在开发一个应用程序,我想在带有自定义单元格的 UITableView 中显示几乎与屏幕大小一样大的图像。 图像加载良好,有点慢,但它们加载了,但是当我在 TableView 中滚动时,它们出现在错误的单元格中(例如,单元格 5 中的 Image1 应该出现,而 Image5 应该出现),1 或 2 秒后,正确的图像出现。 为了避免太多的数据流量,我想到了类似“缓存”的 URL/图像存储,如下所示:

- (id) init
{
    if (self = [super init]) {
        self.cacheStoreDictionary = [NSMutableDictionary new];
    }
    return  self;
}

- (void) startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item
{
    if (self.cacheStoreDictionary[urlString]) {
        UIImage *image = self.cacheStoreDictionary[urlString];
        [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:YES];
    } else {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
            UIImage *image = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.cacheStoreDictionary setObject:image forKey:urlString];
                [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO];
            });
        });
    }
}

我需要通过 AFNetwork 加载 URL 和其余数据,如下所示:

- (void)fetchTicketEvents
{
    // Login URL
    NSURL *eventsURL = [NSURL URLWithString:TH_API_BASEURL];

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:eventsURL];
    httpClient.parameterEncoding = AFJSONParameterEncoding;

    // Set request parameters
    NSDictionary *params = nil;
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:TH_API_PATH_TICKET_EVENT_INDEX
                                                      parameters:params];
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

    // Prepare request
    AFJSONRequestOperation *eventsRequest = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        if ([self.delegate respondsToSelector:@selector(thAPITicket:didLoadTicketEvents:response:errorCode:)]) {
            NSArray *jsonEventArray = JSON;
            NSMutableArray *event = [[NSMutableArray alloc] initWithCapacity:jsonEventArray.count];
            for (NSDictionary *eventDictionary in [JSON allObjects]) {
                [event addObject:[LCEvent eventFromDictionary:eventDictionary]];
            }
            [self.delegate thAPITicket:self
                             didLoadTicketEvents:YES
                                        response:@{@"response" : response, @"json" : JSON, @"event" : event}
                                       errorCode:TH_API_ERR_TICKETINDEX_NO_ERROR];
#if LOG_NETWORKING
            [self printJSON:JSON];
#endif
            //Network indicator off
            [LCSharedInstance hideNetworkActivity];

            //Allow Slide-To-Refresh
            [LCSharedInstance singletone].allowSlideToRefresh = YES;
            [LCSharedInstance singletone].isShownLoadingMessage = NO;
            [LCSharedInstance singletone].isLoading = NO;
        }
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        if ([self.delegate respondsToSelector:@selector(thAPITicket:didLoadTicketEvents:response:errorCode:)]) {
            if (nil == JSON) {
                JSON = @{};
            }
            [self.delegate thAPITicket:self
                             didLoadTicketEvents:NO
                                        response:@{@"response" : response, @"json" : JSON}
                                       errorCode:TH_API_ERR_TICKETINDEX_NO_ERROR];
            [LCSharedInstance hideNetworkActivity];

        }
        //Network indicator off
        [LCSharedInstance hideNetworkActivity];
    }];
    [LCSharedInstance showNetworkActivity];
    // Send request
    [eventsRequest start];
}

这是我填充 TableViewCell 的方法:

- (void) lcCachedImageLoader:(LCCachedImageLoader *)cachedImageLoader didLoadImage:(UIImage *)teaserImage forItem:(id)item wasCacheHit:(BOOL)wasCacheHit
{
    //Teaser Image Implementation
    UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]);
    imageView.alpha = 0.2;
    imageView.image = teaserImage;
    imageView.contentMode = UIViewContentModeScaleToFill;
    [UIView animateWithDuration:0.5 animations:^{
        imageView.alpha = 1.0;
    }];
}


#pragma mark - tableview delegation
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"offerCell";
    LCEvent *event = self.eventArray[indexPath.row];
    tableView = self.tableView;
    LCClusterViewController *clusterVC = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

#pragma mark - Cell Config and Style Attributes
    clusterVC.titleLabel.attributedText = LCAttrText(event.titleString, LCFontStyleEventName);
    clusterVC.ticketDetailsLabel.attributedText = LCAttrText(event.subtitleString, LCFontStyleEventTitle);
    clusterVC.oldPriceLabel.attributedText = LCAttrText(event.oldPriceString, LCFontStyleEventOldPrice);
    clusterVC.actualPriceLabel.attributedText = LCAttrText(event.actualPriceString, LCFontStyleEventPrice);
    clusterVC.timeLabel.attributedText = LCAttrText(event.timeString, LCFontStyleEventInfoText);
    clusterVC.ticketCountLabel.attributedText = LCAttrText(event.stockString, LCFontStyleEventInfoText);
    clusterVC.dateLabel.attributedText = LCAttrText(event.dateString, LCFontStyleEventDateText);
... and on and on

所以感谢任何有用的提示


出于性能原因,表视图单元格会被重用,因此如果您在加载图像之前未将其设置为任何内容,它们将保留 UIImageView 中以前使用的图像。

在调用 startLoadingImageWithUrl 之前,您可以先使用占位符图像设置 imageView 的初始图像,或者在 imageView 顶部添加加载指示器。但请记住在加载真实图像时删除加载指示器。

- (void) startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item
{
    UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]);
    imageView.image = placeholderImage; 
    if (self.cacheStoreDictionary[urlString]) {
        UIImage *image = self.cacheStoreDictionary[urlString];
        [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:YES];
    } else {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
            UIImage *image = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.cacheStoreDictionary setObject:image forKey:urlString];
                [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO];
            });
        });
    }
}

而对于图像加载后出现在错误单元格的情况,这是因为您在 startLoadingImage 和 didLoadImage 中将 item(重复使用的单元格)作为参数传递。尝试传递indexPath,并使用indexPath找到正确的单元格,更新单元格图像视图。

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UITableViewCells 中的图像加载错误 的相关文章

随机推荐

  • 数据向量列表的快速滚动和(二维矩阵)

    我正在寻找一种快速计算滚动和的方法 可能使用 Numpy 这是我的第一个方法 def func1 M w Rtn np zeros M shape 0 M shape 1 w 1 for i in range M shape 1 w 1 R
  • 更改ggplot2中轴文本的字体大小和方向

    我正在绘制一个图表 其中 x 轴上有一个分类变量 y 轴上有一个数值变量 对于 x 轴 由于存在许多数据点 默认文本格式会导致每个刻度线的标签与其他标签重叠 如何 a 更改轴文本的字体大小和 b 更改文本的方向以使文本垂直于轴 Use th
  • Pandas:InvalidIndexError:重新索引仅对具有唯一值的索引对象有效

    我有两个数据框 用于存储有关在商店购买的产品的数据 df1存储有关商店名称 产品 ID 产品名称和购买日期的数据 df2存储有关产品 ID 产品名称和类型的数据 我正在尝试更新df2接收日期值df1但仅适用于该类型的产品P 下面给出的是数据
  • JavaScript - 从数组中的多个输入获取值

    我正在尝试从数组中具有相同 id 的多个输入中获取值 我已经使用了论坛 但还没有找到适合我的解决方案 Exmaple
  • 我什么时候应该使用像 OSGI 这样的平台,什么时候必须避免使用它?

    我的问题非常简单 应用程序的哪些功能迫使开发人员利用类似 OSGI 的系统 在什么情况下不需要这样的实用程序 我刚刚发布了另一个问题的以下链接 OSGi解决什么问题 但我认为这里更合适 Hal Hildebrand 撰写了一篇博客 介绍了他
  • 在 .NET 3.5 中使用反射生成子类列表

    在运行时 我想指定一个父类 然后程序将生成所有子类的列表 无论多少代 例如 如果我有Entity作为父母 并且Item Entity and Actor Entity 将有两个字符串 Actor 和 Item 我看到System Refle
  • 如何向 log4j 消息添加前缀(在对象级别)

    我使用 log4j2 我想为我的所有消息添加前缀 该前缀被传递给构造函数参数 它取决于类的实例 所以我们处于对象级别 而不是类或线程 例如 我有一个A类实例化就像new A 152 所以当我使用log error message 在这堂课上
  • 有没有办法强制 ASP.NET Web API 返回纯文本?

    我需要从 ASP NET Web API 控制器获取纯文本响应 我尝试过提出请求Accept text plain但它似乎并没有达到目的 此外 该请求是外部的 不受我的控制 我要完成的是模仿旧的 ASP NET 方式 context Res
  • 从基类访问子类的静态成员

    我有以下基类 class BaseClass public static myFlag boolean false constructor reference ChildClass myFlag 与儿童班 class ChildClass
  • 当我在 Chrome 中单击“允许”时,为什么 getUserMedia 会抛出 [object NavigatorUserMediaError]?

    最近 我在尝试通过我的网站访问客户的麦克风时开始出现错误 当Chrome询问是否允许网站访问用户的麦克风时 object NavigatorUserMediaError 无论他们点击 允许 还是 拒绝 都会产生 无论麦克风是否实际插入计算机
  • 在Python中分割分号分隔的字符串

    我想分割一个以分号分隔的字符串 以便我可以使用 Python 存储每个单独的字符串 以用作 XML 标记之间的文本 字符串值如下所示 08 26 2009 08 27 2009 08 29 2009 它们只是存储为字符串值的日期 我想迭代每
  • iOS:带有按钮图像的导航栏

    我想创建一个导航栏 其中图像作为导航栏右侧的按钮 像下面的快照 我怎样才能实现这个目标 希望这可以帮助 viewController navigationItem titleView UIImageView alloc initWithIm
  • 如何在 Go 中获取文件的组 ID (GID)?

    os Stat 返回一个FileInfo对象 它有一个Sys 返回一个方法Interface 没有方法 虽然我有能力fmt Printf 它 看到 Gid 我无法以编程方式访问 Gid 我如何在这里检索文件的 Gid file info o
  • 用不同的颜色填充水平线上方和下方的区域[重复]

    这个问题在这里已经有答案了 Aim 我正在尝试填充 R 中 ggplot 生成的图中两条线之间的区域 我想用与水平线下方不同的颜色填充水平线上方的线之间的所有内容 我成功地用单一颜色填充了两条线之间的所有内容 但是 我无法用两种不同的颜色区
  • 通过 PHP 使用 R

    我对 R 比较陌生 对 Linux Ubuntu 命令行也很陌生 我正在尝试用 PHP 编写一个页面 其中包含我想在 R 中执行的命令 然后将结果传回以便能够使用它们 我尝试了下面代码的变体 但我只得到 R 欢迎消息作为我的输出 当我在命令
  • 完成后如何杀死 doMC 工作人员?

    doMC 的文档似乎非常稀疏 仅列出了 doMC package 和 registerDoMC 我遇到的问题是我将通过 doMC foreach 生成几个工作人员 但是当工作完成后 他们只是坐在那里占用内存 我可以去寻找他们的进程ID 但我
  • 如何配置 Play! 2.4.2 HTTPS 密钥库?

    我是 Play Framework 的新手 只是尝试在 Java 8 上首次使用 2 4 2 来使用 HTTPS 我可以让它使用默认密钥库 但不能使用我自己的密钥库 我配置了working默认密钥库位于build sbt javaOptio
  • Android 版 Google 地图 V2 上圆圈上的 LatLng 点

    I need to store all the LatLng points of circle drawn on google map like 我有圆和半径 以米为单位 如何得到那个 我尝试使用代码 private ArrayList
  • 重置数据表中的自动增量

    我填充一个DataSet with a DataAdapter to a SQL CE数据库 数据显示在DataGrid它绑定到 DataSet 的 DataTable 我有一个自动递增 ID 字段 或在 SQLCE 中 称为PRIMARY
  • UITableViewCells 中的图像加载错误

    我正在开发一个应用程序 我想在带有自定义单元格的 UITableView 中显示几乎与屏幕大小一样大的图像 图像加载良好 有点慢 但它们加载了 但是当我在 TableView 中滚动时 它们出现在错误的单元格中 例如 单元格 5 中的 Im