Layouting dynamic subviews in a UITableviewCell, make constrains to margins - ios

In my app, I have a UITableViewCell which can contain an arbitrary UIView (or subclass hereof). I want the view to fit into the UITableViewCell's contentView's margins. And the cell height will be adjusted to the needs of my view.
I've tried various things but with no positive result.
Here's the code. It does not work. :(
It does not fit the margins and the content is wider than the screen size.
What to do?
class CustomView: UIStackView {
class func viewFromNib() -> CustomView {
guard let view = NSBundle(forClass: CustomView.self).loadNibNamed("CustomView", owner: nil, options: nil).first as? CustomView else {fatalError("CustomView not found")}
return view
}
}
class ViewController: UITableViewController {
let customView = CustomView.viewFromNib()
var containerCell: ContainerTableViewCell?
override func viewDidLoad() {
super.viewDidLoad()
containerCell = ContainerTableViewCell.cell(customView, height: nil)
tableView.reloadData()
tableView.estimatedRowHeight = 40
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return containerCell ?? UITableViewCell()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
}
class ContainerTableViewCell: UITableViewCell {
var singleView: UIView?
class func cell(view: UIView, height: CGFloat?) -> ContainerTableViewCell {
let cell = ContainerTableViewCell()
cell.setup(view, height: height)
return cell
}
func setup(view: UIView, height: CGFloat?) {
singleView = view
contentView.addSubview(singleView!)
let margins = contentView.layoutMarginsGuide
singleView?.topAnchor.constraintEqualToAnchor(margins.topAnchor).active = true
singleView?.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = true
singleView?.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
singleView?.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor).active = true
setNeedsLayout()
if let height = height {
contentView.heightAnchor.constraintEqualToConstant(height).active = true
}
}
}

You should implement
optional func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
in your viewController and to know the height of each cell when refreshing the table.

cellForRowAtIndexPath must use a dequeue family method to get your table cell instance:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier:forIndexPath:
Such that the object will be created through its regular constructor, not your factory method. You don't have that flexibility.
So in your subclass, put your generic constraints in awakeFromNib or an overridden constructor. Don't forget to account for the auto-resizing mask which interferes with programmatic constraints, so this field must be set to false:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/translatesAutoresizingMaskIntoConstraints
Finally, within the cellForRowAtIndexPath, you can modify the constraints of the UITableViewCell instance returned by the dequeue call, to get your custom height in there.
Good luck!

Related

Swift UITableViewCell separatorStyle breaking autolayout on iPhone MIni

I have a UITableView which has a UITableViewCell which contains a UIImageView.
The constraints are setup such that the UIImageView has padding 20 points at the top and sides, and a size ratio of 1:1, so the UIImageView will always be square regardless of the device width.
I apply a cornerRadius to the UIImageView so the image is circular.
However.... the autolayout doesn't seem to work on the first load. But after the first load, it works perfectly.
I have tried every known combination of setNeedsLayout or layoutIfNeeded - both inside the UITableViewCell and in the UITableView code. Nothing works the first time it loads.
Please help!
Code looks like this:
class CircularProfileCell: UITableViewCell {
#IBOutlet weak var circularView: UIView!
func setup() {
circularView.layer.cornerRadius = circularView.bounds.height / 2
}
}
class CircularProfileVC: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .none
self.tableView.register(UINib(nibName: "CircularProfileCell", bundle: nil), forCellReuseIdentifier: "CircularProfileCell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CircularProfileCell", for: indexPath) as! CircularProfileCell
cell.setup()
return cell
}
}
Setup looks like this:
Because corner radius is a layer property it does not always play well with auto layout. In addition, I guess you set it up with frame properties of the view (i.e imageView.layer.cornerRadius = imageView.bounds.height/2).
Hence you should try and set the corner radius on the layoutSubviews() function of the cell. This will make sure to render the correct size
override func layoutSubviews() {
super.layoutSubviews()
imageView.layer.cornerRadius = imageView.bounds.height/2
...
}
This only happens when the tableView.separatorStyle = .none
So to fix it I simply leave the separator on, but set the separator color to clear
self.tableView.separatorStyle = .singleLine
self.tableView.separatorColor = UIColor.clear
Thanks to #CloudBalacing for the help. More info about this problem here

Self sizing tableview inside self sizing tableview cell

Let's say I have hierarchy like this:
*TableViewCell
**TableView
***TableViewCell
and all of them should be resizable. Did someone face this kind of problem? In past I've used many workarounds like systemLayoutSizeFitting or precalculation of height in heightForRowAt, but it always breaks some constraints, because TableViewCell has height constraint equal to estimated row height and there appear some kinds of magic behavior. Any ways to make this live?
Current workaround:
class SportCenterReviewsTableCell: UITableViewCell, MVVMView {
var tableView: SelfSizedTableView = {
let view = SelfSizedTableView(frame: .zero)
view.clipsToBounds = true
view.tableFooterView = UIView()
view.separatorStyle = .none
view.isScrollEnabled = false
view.showsVerticalScrollIndicator = false
view.estimatedRowHeight = 0
if #available(iOS 11.0, *) {
view.contentInsetAdjustmentBehavior = .never
} else {
// Fallback on earlier versions
}
return view
}()
private func markup() {
contentView.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.register(ReviewsTableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.snp.makeConstraints() { make in
make.top.equalTo(seeAllButton.snp.bottom).offset(12)
make.left.equalTo(contentView.snp.left)
make.right.equalTo(contentView.snp.right)
make.bottom.lessThanOrEqualTo(contentView.snp.bottom)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ReviewsTableViewCell
cell.viewModel = viewModel.cellViewModels[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ReviewsTableViewCell
cell.viewModel = viewModel.cellViewModels[indexPath.row]
cell.setNeedsLayout()
cell.layoutIfNeeded()
let size = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)
return size.height
}
}
Self sizing tableView class:
class SelfSizedTableView: UITableView {
override func reloadData() {
super.reloadData()
self.invalidateIntrinsicContentSize()
self.layoutIfNeeded()
}
override var intrinsicContentSize: CGSize {
self.setNeedsLayout()
self.layoutIfNeeded()
return contentSize
}
}
This is actually not an answer to the question, but just an explanation.
(Wrote here because of the character count limitation for the comments).
The thing is that you're trying to insert a vertically scrollable view inside another vertically scrollable view. If you don't disable the nested tableview's scroll ability, you will have a glitch while scrolling, because the system wouldn't know to whom pass the scroll event (to the nested tableview, or to the parent tableview).
So in our case, you'll have to disable the "scrollable" property for the nested tableviews, hence you'll have to set the height of the nested tableview to be equal to its content size. But this way you will lose the advantages of tableview (i.e. cell reusing advantage) and it will be the same as using an actual UIScrollView. But, on the other hand, as you'll have to set the height to be equal to its content size, then there is no reason to use UIScrollView at all, you can add your nested cells to a UIStackView, and you tableview will have this hierarchy:
*TableView
**TableViewCell
***StackView
****Items
****Items
****Items
****Items
But again, the right solution is using multi-sectional tableview. Let your cells be section headers of the tableview, and let inner cells be the rows of the tableview.
here is an example of how to make a tableview inside a table view cell with automatic height for the cells.
You should use the 'ContentSizedTableView' class for the inner tableViews.
class ViewController: UIViewController {
#IBOutlet weak var outerTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
outerTableView.rowHeight = UITableView.automaticDimension
outerTableView.estimatedRowHeight = UITableView.automaticDimension
outerTableView.delegate = self
outerTableView.dataSource = self
}
}
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
sizeToFit()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableTableViewCell
return cell!
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
Use xib files to simplify the hierarchy.
Get a tableView on your storyboard, and create a nib file for your tableViewCell(say CustomTableViewCell). Inside it create a tableView and again create one more tableViewCell xib file. Now, no need of setting labels into your xib file,(if you want only labels in cells and nothing else, if not, there is another way of adding constraints)
Say you have an array of text, some strings are long and some are short.
register nib file in CustomTableViewCell and extend it to use Delegate and DataSource.
register this CustomTableViewCell in ViewController.
While declaring a cell in CustomTableViewCell, just do=
cell.textLabel?.text = content
cell.textLabel?.numberOfLines = 0
Use heightForRowAt to set outer tableViewCell's height, and let the inner tableView to scroll inside.

Custom UITableViewCell from XIB: contentView width is always the same

I've created a custom UITableViewCell with an xib file. In there I have placed several labels and views relative to the width of the contentView. Unfortunately the contentView.bounds.width property stays always the same no matter which device is selected.
My ViewController is also loaded from nib:
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
init(title: String) {
super.init(nibName: "ViewController", bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell", forIndexPath: indexPath) as! CustomTableViewCell
return cell
}
}
In the CustomTableViewCell class I print out the width property of the content view:
override func awakeFromNib() {
super.awakeFromNib()
print("self.contentView.bounds.width: \(self.contentView.bounds.width)")
}
This always prints out the width set in the Interface Builder, even though it should follow the width of the tableView which uses AutoLayout:
Trying to set the cell's frame before returning didn't work:
cell.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 71)
If you are using autolayout then count your width in cellforrowAtindexpath and you will get proper width. awakeFromNib gets called before your cell get autolayout so it is giving same width as set in interface builder.
Second thing if you are using autolayout then setting frame has no meaning. if you want to change height or width then you should take outlet of your constraint (height or width) and you can change it's constant to desired value!
If you want to change height only then you can play with heightForRowAtIndexPath with if else which return desire height as per condition!
Swift 4+
You can use following code, it will set the frame of XIB cell and you can adjust content also with help of XIB height and width.
let cellRect = CGRect(x: 0, y: 0, width: postTableView.frame.size.width, height: imageHeight)
cell?.frame = cellRect
Hope it will work

Swift: Expand UITableViewCell height depending on the size of the UICollectionView inside it

Hi everyone. I started learning programming 1 month ago so please be nice if I don't explain my problem well :)
My project is composed of a main UITableView. In each cell of the UITableView, I have a UICollectionView (on horizontal scrolling).
Img 1 : Main view
The width of each UICollectionViewCell is the same as the entire UITableViewCell. My first problem is about sizing the height of the UITableViewCell (which will depend of the size of the UICollectionView itself and the size of the content on top of it).
Img 2 : CollectionView
This has to be done automatically. In fact, the UICollectionViewCells will not have the same height, so when the user will scroll the UICollectionView horizontally, a new UICollectionViewCell will appear (with different height) and the height of the UITableViewCell will have to adapt.
The second problem I have is about sizing the UICollectionViewCell, in fact I will not know in advance what the height of it is going to be (the width is the same as the UITableView). I should import the content from a nib.
So now here is my ViewController file,
the variables:
#IBOutlet weak var tableView: UITableView!
var storedOffsets = [Int: CGFloat]()
the UITableView extension : Create the cell of the UITableView and set delegate of UICollectionView inside it
extension IndexVC: UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 //Temp
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("CellCollectionView") as? CellPost {
let post = self.posts[indexPath.row]
cell.configureCell(post)
return cell
} else {
return CellPost()
}
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? CellPost else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? CellPost else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
the part of the UICollectionView : Add the view from a Nib/xib to the cell
extension IndexVC: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 9 //Temp
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellInCollectionView", forIndexPath: indexPath)
if let textPostView = NSBundle.mainBundle().loadNibNamed("textPostView", owner: self, options: nil).first as? textPostView {
textPostView.configurePost(post.descriptionLbl)
cell.addSubview(textPostView)
textPostView.translatesAutoresizingMaskIntoConstraints = false
cell.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":textPostView]))
cell.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":textPostView]))
}
return cell
}
Make the size of the cell the same as the entire UICollectionView
extension IndexVC: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(collectionView.frame.width, collectionView.frame.height)
}
And I created this extension in the class dedicated for the UITableViewCell (not useful for the problem, but if any of you want to recreate it)
extension CellPost {
func setCollectionViewDataSourceDelegate<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>(dataSourceDelegate: D, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row
collectionView.setContentOffset(collectionView.contentOffset, animated:false) // Stops collection view if it was scrolling.
collectionView.reloadData()
}
var collectionViewOffset: CGFloat {
set {
collectionView.contentOffset.x = newValue
}
get {
return collectionView.contentOffset.x
}
}
If anyone want to use this code, it works great, but I have to hardcode the height of the UITableView with a tableView( ... heightForRowAtIndexPath ...)
I tried everything to make the UITableViewCell adapt to what's inside it (I tried calculating the size of content sent by the Nib I'm putting in the cell, and then send it to tableView( ... heightForRowAtIndexPath ...)
but I can't make it work. I also tried Auto Layouts but maybe I'm doing it wrong. I also think the problem could come from the part that I imported the nib in my cell.
I also have no idea of a way to expand the cell after the user has swiped the UICollectionViewCell, is there any way to create an event when that happens? And maybe call tableView( ... heightForRowAtIndexPath ...) again?
As i understanding you need to auto adjust tableview cell height. so you can use autolayout for adjust cell height.
Write in ViewDidLoad
self.tableView.estimatedRowHeight = 80
self.tableView.rowHeight = UITableViewAutomaticDimension
Before Returning cell in CellForRowAtIndexPath
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
You can find link for autolayout.
enter link description here
In order to solve my problem, I created an array to store the height of each cell of the UITableView (named cellHeight).
I also calculate the height of each cell at the start of the program in an array composed of array (named cellHeightForPost). The main array represent all the TableView cells, each array inside it represent the height of each cell of the 'collectionView'
In order to update the table view everytime I change the collectionView inside it, i used the fonction collectionView(... willDiplayCell...) :
self.tableView.beginUpdates()
cellHeight[collectionView.tag] = cellHeightForPost[collectionView.tag][indexPath.row]
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
self.tableView.endUpdates()
My UITableView size is defined in tableView(... heightForRowAtIndexPath) and tableView(... estimatedHeightForRowAtIndexPath) :
return cellHeight[indexPath.row]
To set the size of the collectionViewCells :
return CGSize(width: collectionView.frame.width, height: cellHeightForPost[collectionView.tag][indexPath.row])

tableview's Row height is not changing , CollectionView is capturing all the unused space instead of resizing itself in the tableViewCell

I put a UICollectionView into the UITableViewCell by following this tutorial and in my UICollectionViewCell, there's a Image View. So when I run my app, the collection view is not resizing itself at the same time in my cell I put a Text View which is resizing itself according to content, see the below images:
In this first image, I have a text view at the top which have some text in it, and below it with (pink background) is my collection view and inside of that with greenBackground is my image view, as you can see that collection view is taking the extra space instead of reducing itself as Text View Did.
in this second image you can see that my textView haves more content then before so its resized itself now overlapping the CollectionView
this is my TableViewCell:
class TableViewCell: UITableViewCell {
#IBOutlet var txtView: UITextView!
#IBOutlet private weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
// collectionView.frame = self.bounds;
// collectionView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCollectionViewDataSourceDelegate
<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
(dataSourceDelegate: D, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row
collectionView.reloadData()
}
var collectionViewOffset: CGFloat {
get {
return collectionView.contentOffset.x
}
set {
collectionView.contentOffset.x = newValue
}
}
}
this is my collectionViewCell
class CollectionViewCell: UICollectionViewCell {
#IBOutlet var imgView: UIImageView!
override func awakeFromNib() {
self.setNeedsLayout()
//
// self.contentView.frame = self.bounds;
// self.contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
}
}
and this is my TableviewController
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return imageModel.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! TableViewCell
cell.txtView.text = txtArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
override func tableView(tableView: UITableView,
didEndDisplayingCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
extension TableViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return imageModel[collectionView.tag].count
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",
forIndexPath: indexPath) as! CollectionViewCell
cell.imgView.frame = CGRectMake(0, 0, collectionView.frame.width, collectionView.frame.height)
cell.imgView.contentMode = .ScaleAspectFit
//cell.addSubview(imageView)
cell.imgView.image = ResizeImage(UIImage(named: imageModel[collectionView.tag][indexPath.item])!, targetSize: CGSizeMake( cell.imgView.frame.width , cell.imgView.frame.height))
//imageView.image = UIImage(named: imageModel[collectionView.tag][indexPath.item])
return cell
}
}
How can I make this collection view to AutoLayout itself according to the content in it? I also tried this:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 100;
but didn't worked (my collection view got disappear) if anybody knows how to do this, then please guide me..
I faced a similar issue when i used collection view inside a table view cell. No matter what i did i couldn't get the table view to resize automatically but the collection view did. Soo instead of autolayout i did it using code.
I ended up having to calculate the size of the label in the collection view numberOfSections in collection view and passing this height using a delegate to the view controller that has the tableView's delegate and dataSource and reloading the appropriate row of the table view.
As it happens, the numberOfSections in collectionview data source gets called everytime and the delegate resizes the table view height.
Some thing like this-
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
[self.delegate setViewHeight:[self getHeightForCellAtIndexPath:[NSIndexPath indexPathForRow:currentSelected inSection:0]]];
return 1;
}
This ought to give you a general idea.
EDIT: Sorry i misunderstood, your question before. Here is something that should work for you:
As per my understanding, you have a table view cell with a label view and collection view inside of it.
Now, inside your table view cell, you should add top, leading and trailing constraints space to the label. Now inside your collection view position your image vertically in the center and add an appropriate top and bottom to the cell superview. Your collection view itself should have a CONSTANT value in leading, trailing, top to label and bottom to superview. Also add a fixed height constraint to your collection View (assuming you want the image sizes to remain the same).
Now lets says View Controller A is the data source for your table view and the table view cell is the data source for your collection view.
In your viewController A, you should write your height for row at indexPath as-
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGSize stringSize = [yourStringArray[indexPath.row] boundingRectWithSize:CGSizeMake(_yourCollectionView.frame.size.width, FLT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName:[UIFont yourFont size:yourFontSize]} context:nil].
return stringSize.height + 35; //magic number 35, play around with it to suit your need. Did this to always have a minimum fixed height.
}
This will allow your tableViewRowForHeight for that particular index to have the height of your label added to it and the constraints ought to do the rest.

Resources