0
votes

I'm going through Stanford's cs193p. Assignment 4 has us create a custom UITableVIewCell and load a picture from the web into a UIImageView inside the cell.

My UIImageView and my Cell have their content mode set to Aspect Fit on the story board.And the ImageView is set on autolayout to be hugging the cell. And yet when the picture first loads, it will bleed out of the UIImageView. When I click on it, it will correctly aspect fit.

I tried setting the content mode in code just before assigning the image, but that also didn't work. I also tried calling layoutSubviews() and setNeedsLayout right after assigning the image, and while that helps by actually showing the image (as opposed to showing nothing until the user clicks the cell), it still shows in the wrong size until the user clicks it.

This is the UIImageView's constraints

This is the code for the cell:

import UIKit


class ImageTableViewCell: UITableViewCell {
    @IBOutlet weak var pictureView: UIImageView!

    var pictureURL: URL? {
        didSet {
            fetchImage()
        }
    }

    fileprivate func fetchImage() {
        if let url = pictureURL {
            pictureView.image = nil
            let queue = DispatchQueue(label: "image fetcher", qos: .userInitiated)
            queue.async { [weak weakSelf = self] in 
                do {
                    let contentsOfURL = try Data(contentsOf: url)

                    DispatchQueue.main.async {
                        if url == self.pictureURL {
                            weakSelf?.pictureView?.image = UIImage(data: contentsOfURL)
                            weakSelf?.layoutSubviews()
                            print("loaded")
                        }
                    }
                } catch let exception {
                    print(exception.localizedDescription)
                }
            }
        }
    }
}

This is the code that loads the cell on its TableViewController:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
        switch indexPath.section {
        case 0:
            cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath)
            if let imageCell = cell as? ImageTableViewCell {
                imageCell.pictureURL = tweet?.media[indexPath.row].url
        // other stuff not programmed yet
        }
        return cell

The code that gives me the cell's height:

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == 0 && tweet != nil {
            let media = tweet?.media[indexPath.row]
            return tableView.frame.width / CGFloat(media!.aspectRatio)
        }
        return UITableViewAutomaticDimension
    }

I'm sorry for pasting all this code, but I have no idea where the problem is so I'm putting everything I can this might be related.

2
I'm not sure but I think you may have to reload that particular cell after you are done fetching the image and setting it inside the cell! Also shouldn't you only fetch the image if the UIImageView is already nil instead of setting it to nil everytime the function is called?Rikh
@Rikh this is what the instructor does. I think it's because the cells are reusable so you want to clear the contents from a previous call. I reload the cell by calling setNeedsLayout() or layoutSubviews() just after assigning the image. And while that actually gets the image to show (instead of a blank screen) it doesn't adjust to the right size (aspect fit).Augusto Dias Noronha

2 Answers

0
votes

You should set content mode first and then you should set the frame of your imageview, so once you should try to set content mode in awakeFromNib of tableview subclass or from cellforrowatindexpath before setting image to it!

Or you can set your content mode from interface builder (from storyboard!) - > select your imageview - > fro attribute inspector - > select mode(under view) to Aspect fit

0
votes

Well, following an answer on reddit, I deleted the table view controller and remade it, setting all the outlets again. It worked, I guess it was a problem in Xcode?

So if you're having a problem like this, try remaking your storyboard.