Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift UICollectionView in a UITableViewCell dynamic layout can't change cell height

In Xcode 8.2.1 and Swift 3 I have a UICollectionView inside a UITableViewCell but I can't get the layout right. basically I want to be able to see all of the star. I can adjust the size of the star but I want to fix the underlying problem, expanding the blue band.

Here is a shot of the view The red band is contentView and the blue band is collectionView. At first glance it looks like collectionView height is the problem but it is actually being hidden by something else. I can't find or change whatever it is hiding the collectionView cell.

collectionView inside tableView cell

I am not using the storyboard beyond a view controller embedded in a navigator.

Here's all the relevant code.

class WishListsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var tableView: UITableView = UITableView()        
let tableCellId = "WishListsCell"
let collectionCellId = "WishListsCollectionViewCell"

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self        
    tableView.dataSource = self 
    tableView.backgroundColor = .white
    tableView.register(WishListsCell.self, forCellReuseIdentifier: tableCellId)
    self.view.addSubview(tableView)
    tableView.translatesAutoresizingMaskIntoConstraints = false

    tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    }

        func numberOfSections(in tableView: UITableView) -> Int {        
            return wishLists.count
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 1
        }

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{        
            let cell = tableView.dequeueReusableCell(withIdentifier: tableCellId, for: indexPath) as! WishListsCell      
            return cell
        }

        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {    
            return 100
        }

  func tableView(_ tableView: UITableView,willDisplay cell: UITableViewCell,forRowAt indexPath: IndexPath) {

    guard let tableViewCell = cell as? WishListsCell else { return }
    //here setting the uitableview cell contains collectionview delgate conform to viewcontroller
      tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forSection: indexPath.section)
    tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}

func tableView(_ tableView: UITableView,didEndDisplaying cell: UITableViewCell,forRowAt indexPath: IndexPath) {

    guard let tableViewCell = cell as? WishListsCell else { return }
    storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}

extension WishListsViewController: UICollectionViewDelegate , UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionCellId, for: indexPath) as! WishListsCollectionViewCell
    return cell
    }

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 100, height: 100)
}

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

func collectionView(_ collectionView: UICollectionView, layout
    collectionViewLayout: UICollectionViewLayout,
                    minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

}

class WishListsCell: UITableViewCell {

private var collectionView: UICollectionView!
let cellId = "WishListsCollectionViewCell"


    var collectionViewOffset: CGFloat {
        get { return collectionView.contentOffset.x }
        set { collectionView.contentOffset.x = newValue }
    }


    func setCollectionViewDataSourceDelegate<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
        (dataSourceDelegate: D, forSection section : Int) {

        collectionView.delegate = dataSourceDelegate
        collectionView.dataSource = dataSourceDelegate
        collectionView.tag = section
        collectionView.reloadData()
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        collectionView = UICollectionView(frame: contentView.frame, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.backgroundColor = .blue
        collectionView.register(WishListsCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
        contentView.backgroundColor = .red
        self.contentView.addSubview(collectionView)        
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class WishListsCollectionViewCell: UICollectionViewCell {

    var imageView: UIImageView

    override init(frame: CGRect) {
        imageView = UIImageView()
        super.init(frame: frame)
        contentView.addSubview(imageView)        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
        contentView.translatesAutoresizingMaskIntoConstraints = false
        imageView.backgroundColor = .white

        NSLayoutConstraint.activate([

            NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal,
                               toItem: contentView, attribute: .width,
                               multiplier: 1.0, constant: 0.0),

            NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal,
                               toItem: contentView, attribute: .height,
                               multiplier: 1.0, constant: 0.0),

            ])
    }    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
like image 608
markhorrocks Avatar asked Mar 11 '23 03:03

markhorrocks


1 Answers

You can Use View Debugging

Run the project, go back to Xcode and click on the Debug View Hierarchy button in the Debug bar. Alternatively, go to Debug\View Debugging\Capture View Hierarchy.

enter image description here

Now you can select your red view and Xcode will indicate which view is selected.

enter image description here

For more info. Check out: View Debugging in Xcode

like image 72
Warif Akhand Rishi Avatar answered Apr 26 '23 09:04

Warif Akhand Rishi