代码之家  ›  专栏  ›  技术社区  ›  Brad

UITableView中延迟的UIImageView渲染

  •  27
  • Brad  · 技术社区  · 15 年前

    UITableView 习惯地 UITableViewCell 每个都包含一个 UIImageView 其图像正在通过 NSURLConnection

    问题是,当表格滚动时,新图像会在后台正确下载,但直到表格停止移动后才会呈现。

    谢谢

    --更新--

    仔细观察后,我发现 NSURL连接

    4 回复  |  直到 15 年前
        1
  •  65
  •   Daniel Dickison    15 年前

    在停止滚动之前,连接委托消息不会触发的原因是,在滚动期间,运行循环处于激活状态 UITrackingRunLoopMode . 默认情况下, NSURLConnection 将自己安排在 NSDefaultRunLoopMode 只有这样,滚动时不会收到任何消息。

    UITrackingRunLoopMode :

    NSURLRequest *request = ...
    NSURLConnection *connection = [[NSURLConnection alloc]
                                   initWithRequest:request
                                   delegate:self
                                   startImmediately:NO];
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
                forMode:NSRunLoopCommonModes];
    [connection start];
    

    请注意,您必须指定 startImmediately:NO 在初始化器中,它似乎与苹果的文档相反,该文档建议即使在运行循环启动后也可以更改运行循环模式。

        2
  •  1
  •   benzado    15 年前

    您应该仔细阅读nsrunlop。我怀疑,在滚动期间,run循环正在NSEventTrackingRunLoop模式下运行,而NSURLConnection不包括在该模式中。您可能可以通过调用NSURLConnection的scheduleinrunload:forMode:,从而在滚动过程中进行下载。

        3
  •  1
  •   ohhorob    15 年前

    如果您包装您的图像下载&更新在NSO操作中,更新将在表视图滚动时发生。

    NSOperation的另一个好处是,您可以在单元格滑出屏幕时取消该操作。它对用户的反应会更灵敏。。尤其是当他们快速滚动一长串的列表时。今年的苹果技术讲座鼓励了这种技术。

    如果您的列表没有那么长,或者您希望继续加载,那么您可以改为操纵NSOperation优先级。

        4
  •  0
  •   captain cosmic    15 年前

    首先,在连接到mainRunLoop之前,您的连接可能还没有启动,而滚动动画也在这里进行处理。

    我遇到了同样的问题,并通过告诉图像的连接在创建后立即启动来修复它。

        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:wrapper.request delegate:wrapper];
    
        [connection start];
    

        NSInteger itemIndex = theIndexInTheRowDataOfTheCellYouStuffedTheImage
    
        NSArray *indicies = [_tableView indexPathsForVisibleRows];
        NSUInteger rows = indicies.count;
    
        if (rows > 0 &&
            itemIndex >= ((NSIndexPath *)[indicies objectAtIndex:0]).row &&
            itemIndex <= ((NSIndexPath *)[indicies objectAtIndex:rows - 1]).row)
        {       
            [_tableView reloadData];
        }