从 JSON 中的 URL 加载的图像视图在滚动时发生变化

Posted

技术标签:

【中文标题】从 JSON 中的 URL 加载的图像视图在滚动时发生变化【英文标题】:Imageviews loaded from URLs in JSON change upon scrolling 【发布时间】:2014-04-16 00:10:21 【问题描述】:

我正在将 JSON 文件中的图像 URL 异步加载到 UITableView 上的图像视图中。图像会正确加载,但是当我向下滚动提要时,用户的个人资料图片会更改为默认头像(在用户未加载个人资料照片时使用)。我的 php 有必要的 if 语句来首先检查是否有与该用户关联的个人资料图片。当代码看到没有关联的照片时,它自然会加载默认头像。

所以...当应用程序启动时,我会看到提要和(几秒钟后...也许对此也有帮助?)提要中的图像加载,但是当我滚动过去并返回时,它们是现在显示为默认头像,并慢慢变回相应的关联图像。我真的不知道从哪里开始……这是缓存问题吗?不应该在页面加载之前加载图像吗?非常感谢修复我的代码的任何帮助!

我的 PHP 文件:

$posted="posted";

$query1 = $conn->prepare('SELECT * FROM users WHERE ID=:id');
$query1->bindParam(':id', $_SESSION['uid']);
$query1->execute();
$row = $query1->fetch();
$username="dvdowns";

$zero=0;
$posted="posted";

$query = $conn->prepare('
SELECT description, city, status, state, christmas, country, 
needsusername, howmanypeopleneeded, howmanypeoplesignedup, 
needs.orgname, needs.ID, titleofneed, expiredate, datesubmitted 
FROM needs INNER JOIN follow ON follow.followname = needs.needsusername 
WHERE follow.username = :username AND needs.christmas=:zero 
AND needs.status=:posted ORDER BY datetime DESC LIMIT 0, 10');
$query->bindParam(':username', $username);
$query->bindParam(':zero', $zero);
$query->bindParam(':posted', $posted);
$query->execute();

$arr = array();

while ($rows = $query->fetch()) 
    $title=$rows['titleofneed'];
    $description=$rows['description'];
    $needsusername=$rows['needsusername'];

    $query1 = $conn->prepare('SELECT * FROM users WHERE username=:username');
    $query1->bindParam(':username', $needsusername);
    $query1->execute();
    $row = $query1->fetch();
    $photo=$row['photo'];

    if ($photo=="") 
        $photo = "http://domain.com/images/default.png";
    
    else 
        $photo="http://www.domain.com/".$photo;
    

    $arr['needTitle'] = $title;
    $arr['needPoster'] = $needsusername;
    $arr['needDescrip'] = $description;
    $arr['userImage'] = $photo;
    $data[] = $arr;


echo json_encode($data);

我的 TableViewController.m 文件:

    NSURL *myURL = [[NSURL alloc]initWithString:@"http://domain.com/json2.php"];
    NSData *myData = [[NSData alloc]initWithContentsOfURL:myURL];
    NSError *error;

    jsonArray = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:&error];

    [tableView reloadData]; // if tableView is unidentified make the tableView IBOutlet


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    // Return the number of rows in the section.
    return jsonArray.count;



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


    NeedCardTableViewCell *cell = (NeedCardTableViewCell *) [tableView dequeueReusableCellWithIdentifier:@"needCard" forIndexPath:indexPath];

    NSDictionary *needs = jsonArray[indexPath.row]; // get the data dict for the row
    cell.textNeedTitle.text = [needs objectForKey: @"needTitle"];
    cell.textNeedPoster.text = [needs objectForKey: @"needPoster"];
    cell.textNeedDescrip.text = [needs objectForKey: @"needDescrip"];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
        NSURL *imageURL = [NSURL URLWithString:needs[@"userImage"]];
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
        dispatch_async(dispatch_get_main_queue(), ^
            [cell.imageProfPic setImage:image];
        );
    );

    return cell;

【问题讨论】:

我已经实现了 AFNetworking 库并在这里发布了一个新问题:link 【参考方案1】:

使用下面的代码:

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

        NeedCardTableViewCell *cell = (NeedCardTableViewCell *) [tableView dequeueReusableCellWithIdentifier:@"cell"];

        if (cell == nil)
        
            cell = [[NeedCardTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
        

        NSDictionary *needs = jsonArray[indexPath.row]; // get the data dict for the row
        cell.textNeedTitle.text = [needs objectForKey: @"needTitle"];
        cell.textNeedPoster.text = [needs objectForKey: @"needPoster"];
        cell.textNeedDescrip.text = [needs objectForKey: @"needDescrip"];

cell.tag = indexPath.row;

cell.imageView.image = nil;
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
        dispatch_async(queue, ^(void) 

            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:needs[@"userImage"]];

            UIImage* image = [[UIImage alloc] initWithData:imageData];
            if (image) 
                 dispatch_async(dispatch_get_main_queue(), ^
                     if (cell.tag == indexPath.row) 
                         cell.imageView.image = image;
                         [cell setNeedsLayout];
                     
                 );
             
        );

        return cell;
    

如果从代码创建单元格,请确保您已在 viewDidLoad 方法中注册它:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

如果您使用的是故事板单元原型,请跳过此行。

【讨论】:

对不起朋友,还是一样的情况。为了清楚起见,我正在使用故事板单元原型。我的 ReuseIdentifier 是“needCard”,我已将您的“Cell”字符串更改为。这是正确的吗? 好的,所以你不需要在 viewDidLoad 中注册一个类。只要确保您使用相同的标识符即可。在情节提要上打开您的单元格,复制单元格标识符值并将其粘贴到您的代码中,而不是我的 @"cell" 标识符 还有 JFY 代码中有两个 @"cell" 字符串,所以用你的来修改 是的,我就是这么做的。刚刚提到这一点是为了确保我在同一页面上。页面加载相同。只要我滚动到默认头像,图像就会发生变化。 我已经更新了代码,但您可以更轻松地使用 AFNetworking。这是一个答案如何做到这一点***.com/questions/19501652/…

以上是关于从 JSON 中的 URL 加载的图像视图在滚动时发生变化的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 在滚动时重新加载错误的图像

表格视图中的图像加载另一个几秒钟

UICollectionView在滚动时重新加载错误的图像

从 URL 下载图像并添加到滚动视图子视图

iPhone - 从 URL 加载图像时内容不会滚动

使用 url 图像平滑滚动的表格视图