1

I'm asynchronously loading image URLs from my JSON file into imageviews on my UITableView. The images load appropriately, however when I scroll down the feed, the user's profile picture changes to the default avatar (used when the user hasn't loaded a personal profile photo). My php has the required if statement to first check if there is a profile pic associated with that user. When the code sees there is no photo associated, it naturally loads the default avatar.

So...when the app launches, I see the feed and (after a few seconds...maybe help with that too?) the images in the feed load, but when I scroll past them and return, they are now displayed as the default avatar, and slowly change back to the appropriate associated image. I don't really have a clue where to begin with this...is it a cache issue? Shouldn't the images be loaded before the page loads? Any help with fixing my code is greatly appreciated!

My PHP file:

$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);

My TableViewController.m file:

    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;
davidrayowens
  • 1,562
  • 2
  • 13
  • 23
  • I've implemented the AFNetworking library and have posted a new question here: [link](http://stackoverflow.com/questions/23122654/loading-imageviews-with-afnetworking-via-json-hierarchy-and-objectforkey) – davidrayowens Apr 17 '14 at 00:59

1 Answers1

0

Use this code below:

    - (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;
    }

Also be sure that you have registered it in viewDidLoad method if create cell from code:

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

If you are using storyboard cell prototype just skip this line.

Matrosov Oleksandr
  • 25,505
  • 44
  • 151
  • 277
  • Sorry friend, still in the same situation. Just to be clear, I am utilizing the storyboard cell prototypes. My ReuseIdentifier is "needCard", which I have changed your "Cell" strings to. Is this correct? – davidrayowens Apr 16 '14 at 00:29
  • 1
    ok so then you don't need register a a class in viewDidLoad. Just be sure that you use the same identifier. Open your cell on storyboard, copy cell identifier value and paste it to your code instead of my @"cell" identifier – Matrosov Oleksandr Apr 16 '14 at 00:34
  • 1
    also JFY there are two @"cell" strings in the code so modify both with yours – Matrosov Oleksandr Apr 16 '14 at 00:34
  • Yeah, that's what I did. Just mentioned that to make sure I'm on the same page. The page loads the same. The images change as soon as I scroll away to the default avatar. – davidrayowens Apr 16 '14 at 00:35
  • I have updated code, but you can use AFNetworking it more easiest. This is an answer how to do it http://stackoverflow.com/questions/19501652/how-to-download-image-with-afnetworking-2-0 – Matrosov Oleksandr Apr 16 '14 at 00:57
  • Haha, well...the updated code caused my profile pics to take up the size of the screen and stack vertically, with my prototype cells behind them. Unfortunately, the images still disappear when scrolled away from, and upon return, they slowly load again. I'll give the AFNetworking a shot. – davidrayowens Apr 16 '14 at 01:01
  • I've implemented the AFNetworking library and have posted a new question here: [link](http://stackoverflow.com/questions/23122654/loading-imageviews-with-afnetworking-via-json-hierarchy-and-objectforkey) – davidrayowens Apr 17 '14 at 00:58