user1046037 user1046037 - 3 months ago 55
Swift Question

Collection view height incorrect when used with UIPageControl

Overview



There is a
UICollectionViewCell
that contains an imageView.

Above the collection view there is a
UIPageControl


The image is got from the photo library and displayed.

Problem




  • The first time alone the image in collection view exceeds the top boundary.

  • UIPageControl
    height is not determined while the collection view loads.

  • I get the following error:



Error:



the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.


Points to note:




  • This
    UICollectionViewController
    is added as a child controller to
    UIStackView
    .

  • The above problem only occurs for the first time, when I remove from child view controller and add again, the issue is resolved.



Question:




  • Why is the image overflowing it's boundaries in spite of setting constraints and using aspect fit ?

  • How to fix this issue ?



Collection View Cell:



class PhotoBrowserCell : UICollectionViewCell {

let imageView = UIImageView()


//MARK: Initializers

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)

setup()
}

override init(frame: CGRect) {
super.init(frame: frame)

setup()
}


//MARK: Setup

private func setup() {

setupBaseView()
setupImageView()
}

private func setupBaseView() {
backgroundColor = UIColor.blueColor()
}

private func setupImageView() {

imageView.image = UIImage(named: "PlaceHolder")
imageView.contentMode = .ScaleAspectFit
imageView.clipsToBounds = true

imageView.setContentHuggingPriority(1000, forAxis: .Vertical)

contentView.addSubview(imageView)

imageView.translatesAutoresizingMaskIntoConstraints = false

let insets = UIEdgeInsets(top: 10, left: 20, bottom: 30, right: 20)

imageView.leadingAnchor.constraintEqualToAnchor(contentView.leadingAnchor, constant: insets.left).active = true
imageView.trailingAnchor.constraintEqualToAnchor(contentView.trailingAnchor, constant: -insets.right).active = true
imageView.topAnchor.constraintEqualToAnchor(contentView.topAnchor, constant: insets.top).active = true
imageView.bottomAnchor.constraintEqualToAnchor(contentView.bottomAnchor, constant: -insets.bottom).active = true
}
}


Request Asset from photo library:



private func requestAssetSelected() {

let size = imageViewSize

if let assetSelected = assetSelected {

cachingManager.requestImageForAsset(assetSelected,
targetSize: size,
contentMode: .AspectFit,
options: nil) { [weak self] image, info in

//This completion handler might be called multiple times
//First time it provides a temporary image and then shows a full size image
//So ensure it is not a temporary (degraded) image
if let image = image,
isDegraded = info?[PHImageResultIsDegradedKey] as? Int where isDegraded == 0 {
self?.imagesToUpload.append(image)
self?.photoBrowser.reload()
}
}
}
else {
photoBrowser.reload()
}
}

Answer

Root Cause:

  • The collection view cell height calculation was wrong
  • Cell height was wrong because the collection view height was wrong
  • Collection view height was wrong because the UIPageControl was zero while collection view was populated. And much later the UIPageControl height was computed.
  • UIPageControl was using it's intrinsic size.

This is the reason why it only happened the first time.

Solution:

Add a height constraint, so that it doesn't have to depend on it's intrinsic height calculation:

pageControl.heightAnchor.constraintEqualToConstant(38).active = true
Comments