UITableViewAutomaticDimension + AFNetworking

267 views Asked by At

I'm loading images from an API, and they have different heights and displaying in a UITableView which contains other type of cells (the reason I'm using UITableViewAutomaticDimension)

I wanted to display (or reload) the cells containing the images using the image height, to avoid distortion.

I tried different solutions, but I'm having a hard time getting it to work? Any tips or suggestions on how I can solve this?

Thank you

EDIT:

I uploaded an example project here https://github.com/LucasCoelho/ImageLoading

The crash error is

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8]'

I'm thinking it might be related to those conflicting NSAutolayoutConstraints

(
    "<NSLayoutConstraint:0x7f85db176750 V:[UIImageView:0x7f85db17a090(72)]>",
    "<NSLayoutConstraint:0x7f85db18ca90 V:|-(0)-[UIImageView:0x7f85db17a090]   (Names: '|':UITableViewCellContentView:0x7f85db179f70 )>",
    "<NSLayoutConstraint:0x7f85db18cb80 V:[UIImageView:0x7f85db17a090]-(0)-|   (Names: '|':UITableViewCellContentView:0x7f85db179f70 )>",
    "<NSLayoutConstraint:0x7f85db197e50 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f85db179f70(128)]>"
)
1

There are 1 answers

2
salabaha On BEST ANSWER

First you need to add height constraint to you imageView and create reference to it from you UITableViewCell subclass.

class TableViewCell: UITableViewCell {
      @IBOutlet weak var imageView: UIImageView!
      @IBOutlet weak var imageViewHeightConst: NSLayoutConstraint!
}

Then make use of UIImageView+AFNetworking.h method:

- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
          placeholderImage:(UIImage *)placeholderImage
                   success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
                   failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;

In success block you will need to set to downloaded image to your imageView and update imageViewHeightConst constant property.

imageView.image = image
imageViewHeightConst.constant = image.size.height

Also you need a way to inform your tableview that image has been downloaded and tableview should be updated. So you can use delegate patter to solve this problem. In the implementation of delegate method you can update table view by using code below:

 tableView.beginUpdates()
 tableView.endUpdates() 

Eventually your cell subclass will look similar to this:

@objc protocol TableViewCellDelegate {
    func tableViewCell(cell: UITableViewCell, didLoadImage: UIImage)
}

class TableViewCell: UITableViewCell {
    @IBOutlet weak var photoImageView: UIImageView!
    @IBOutlet weak var imageViewHeightConst: NSLayoutConstraint!

    weak var delegate: TableViewCellDelegate?
}

extension TableViewCell {

    func configureCellForURL(url: NSURL, placeholderImage: UIImage) {
        let request = NSURLRequest(URL: url)
        photoImageView.setImageWithURLRequest(request, placeholderImage: placeholderImage, success: { [weak self] (request, response, image) -> Void in

            self?.photoImageView?.image = image
            self?.imageViewHeightConst?.constant = image.size.height
            self?.delegate?.tableViewCell(self!, didLoadImage: image)

        }) { (request, response, error) -> Void in

        }
    }
}