10

I'm developing an iOS application that loads posts from a server into a UICollectionView. The collection view cell includes a UIImageView that is fixed to the bottom of the cell.

UICollectionViewCell

Whenever I start the application and the collection view loads, all the images do not load correctly but for the last image, which is the correct dimensions. All cells are being formatted the same way.

UICollectionView

I have tried a multitude of solutions but nothing so far has worked.

What I suspect is happening is that the images have not finished loading before being set to the UIImageView of each cell (except for the last one in this case). This doesn't seem possible though as the cells are reloaded after getting a successful response..

This is my code for that particular function (using Alamofire)

func getAllPosts(){

    let url =  "\(Constants.baseURL)/posts/"
    let parameters = ["user_id": "\(userProfile!.getId())"]

    Alamofire.request(.POST, url, parameters: parameters, encoding: .JSON)
        .validate(contentType: ["application/json"])
        .responseString { response in
            switch response.result {

            case .Success:

                var postsArray = Array<[String: AnyObject]>()

                do {

                    let json = try NSJSONSerialization.JSONObjectWithData(response.data!, options: NSJSONReadingOptions.MutableContainers)



                    for post in json as! [AnyObject] {

                        postsArray.append(post as! [String: AnyObject])

                    }

                    //invert array of posts so that latest load first!

                    postsArray = postsArray.reverse()

                } catch {

                }

                //convert json to Post objects and reload the view

                self.initialisePosts(postsArray)

                self.collectionView?.reloadData()


            case .Failure(let error):
                print(error)
            }
    }  
}

All help is appreciated.

Edit: Below are the current constraints on the UIImageView

Constraints

Edit 2: Here is the code for formatting the cells

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    // get a reference to our postcell with no image
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifiers[0], forIndexPath: indexPath) as! PostCell

    guard let _: Post? = posts[indexPath.row] else {
        return cell
    }

    return configurePostCell(cell, post: posts[indexPath.row])!
}

func configurePostCell(cell: UICollectionViewCell, post: Post) -> PostCell?{
    if let cell = cell as? PostCell {

        cell.author.text = post.user_name
        cell.date.text = formatter.stringFromDate(post.pub_date!)
        cell.desc.text = post.desc


        cell.layer.cornerRadius = 5 //set corner radius here

        cell.advertImage.image = post.advert?.advert_image


        return cell
    }

    return nil
}

Update: Using @Michael's Advice I have found that the Cell images are loading correctly..

Correctly loading image

but that the cell height is being mysteriously cropped by 50px..

Storyboard editor cell size

Storyboard editor cell size

Cell size at run-time

Cell size at run-time

This seems to be the issue but I have not found a solution yet.

Update: With two hours left on the bounty I have decided to award it to @Michael because his answer helped me to further investigation of my issue, which is still ongoing.

Danoram
  • 8,132
  • 12
  • 51
  • 71
  • 1
    Where is your code for setting images to collection view? Have you given height constraint for UIImageView? – Vishal Sonawane Aug 01 '16 at 11:44
  • oh yes sorry I will edit the question now to include that information. – Danoram Aug 01 '16 at 11:45
  • do it in the main_queue – Özgür Ersil Aug 01 '16 at 11:45
  • Do you mean reload the collection view data in the main_queue or format the cells in the main_queue or something else? – Danoram Aug 01 '16 at 11:53
  • 1
    I don't think running on the main_queue is the problem, Alamofire requests already take place on the main queue – kye Aug 01 '16 at 11:56
  • @Danoram Try to set break points at the methods and check if your collectionView is actually reloading after your response or not? – Vishal Sonawane Aug 01 '16 at 12:06
  • After some investigation I think the way in which the server returns the images may be the problem. Requesting any of the images from the server using postman gives a "414 Request-URI Too Long".. – Danoram Aug 01 '16 at 12:43
  • I still haven't found a solution to this problem but thinking forward, should I be getting each 'post' object in json with the images as encoded strings within the response? or should I be returning them separately using individual api calls that include only the image data in the response? I think that the size of the post list response is too long in any case.. – Danoram Aug 03 '16 at 23:18
  • Is it possible that the `desc` field contains multiple blank lines in all but the last post, pushing down the image in the cell? – Peter Alfvin Aug 14 '16 at 14:03
  • I've checked and there doesn't appear to be any trailing whitespace in the `desc` field and it has only one Line set in the storyboard editor. It also doesn't have any constraints between it and the `UIImageView` that would push it down. I've technically solved the problem by moving the UIImageview up `50px` and reducing the height of the cell by `50px` also. But I'd like to know why I can't set a custom size for the cell and why it reverts to 300x200 :c – Danoram Aug 15 '16 at 01:32

2 Answers2

3

Firstly, use the Debug View Hierarchy button to check for anomalies in the table cells at runtime.

Then breakpoint on the cell creation and inspect the UIImage you are about to set to the cell and make sure the size is right. If you assign the image you downloaded to a local variable you can probably quicklook it too, to see if it looks right.

Then, if all that seems sensible, check your auto-layout code is robust.

Check by removing the downloading of images from the situation. I would do this:

  1. Remove setting of the image at all, but set the image background to UIColor.Red or something and check they all layout nicely as little more than normal UIViews.
  2. Embed an image in the app bundle as a PNG and set it instead of the downloaded image. Again, look at how it renders.
  3. Try a different sizes image in the app bundle and check again (if relevant - maybe all your images are the same size anyway)

If that all looks good, then you know it's around the download or layout of those server images.

Michael
  • 1,213
  • 6
  • 9
  • Hi Michael. Thanks for your advice! I've managed to find using the Debug View Hierachy that the cells are actually being cropped by 50px. I've updated my question. – Danoram Aug 13 '16 at 03:29
  • Is that aspect ratio constraint correct? It looks like 15:4 would produce an image height of 80 for a cell width of 300 (assuming when you run it the cells are 300 points wide). Is that the image height you were expecting? (300/15)*4 = 80 – Michael Aug 14 '16 at 20:40
  • Yes the image height will be `80px` for a cell width of `300` but only has a visible height of `30px` currently because the cell is being cropped by `50px` at the bottom. I don't seem to be able to set the custom size to `300x250` as it reverts to `300x200` at runtime.. – Danoram Aug 15 '16 at 01:34
0

Change 15:4Ratio to a Constant Height(80px),And set heightForRowAtIndexPath to a Constant height (250px)

Bill Xie
  • 105
  • 6
  • That'd work, although you shouldn't need to remove the ratio constraint, unless it must be a fixed 80point no matter what size the screen. Which if it is, then this is totally the right thing to do. But ff you want the cells to scale depending on the screen width then you should set the table.rowHeight to UITableViewAutomaticDimension and the estimatedRowHeight to 250. (see https://www.raywenderlich.com/129059/self-sizing-table-view-cells) – Michael Aug 15 '16 at 15:24
  • I'd set heightForRowAtIndexPath SCREEN_WIDTH / ratio Set Image with a ratio – Bill Xie Aug 16 '16 at 07:40