Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling `[UIView -systemLayoutSizeFittingSize:]` on a UITableViewCell always fails

I want to use auto-layout for UITableViewCells. These table cells have a dynamic height (depending on text length).

I'm using [UIView -systemLayoutSizeFittingSize:] to calculate the appropriate cell height (to return in [UITableView -heightForRowAtIndexPath:]) but I keep getting the following results:

  • If I pass UILayoutFittingCompressedSize, I get back a CGSize of (0,0).

  • If I pass UILayoutFittingExpandedSize, my app crashes with this error:

    *** Assertion failure in -[NSISLinearExpression incrementConstant:], /SourceCache/Foundation_Sim/Foundation-1043.1/Layout.subproj/IncrementalSimplex/NSISLinearExpression.m:620

(My guess is that this means some number is infinite.)

My implementation is simple. I calculate the height for each object, and then cache it:

MessageCell *cell = // allocate a new cell...

//  set up the cell (assign text, images, etc)

CGSize size = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

self.cellHeight = size.height;  // size always equals (0, 0)

I hypothesize that this is a problem with the constraints I set, but:

  • If I manually set cellHeight to a large value, the cells all look fine except the height is wrong.
  • Interface Builder gives me no warnings about ambiguous restraints
  • [cell hasAmbiguousLayout] returns NO.
  • My cell has, among other things, an image set at 48x48, so a size of (0, 0) shouldn't satisfy all the constraints.

Any ideas?

like image 484
Aaron Brager Avatar asked Jul 10 '13 16:07

Aaron Brager


People also ask

How do you get the Indexpath row when a button in a cell is tapped?

You can walk up the view hierarchy to find the containing table view cell and the containing table view. Then you can ask the table view for the cell's index path. Then use it to find the index path like this: func addButtonTapped(_ sender: Any) { guard let button = sender as?

How to increase height of cell in tableView in iOS swift?

To change the height of tableView cell in ios dynamically, i.e resizing the cell according to the content available, we'll need to make use of automatic dimension property. We'll see this with the help of an sample project.


2 Answers

This is what works for me (note 'contentView')

CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

EDIT: I answered a similar question and provided a complete example, here:

How to resize superview to fit all subviews with autolayout?

like image 191
TomSwift Avatar answered Sep 17 '22 14:09

TomSwift


It is hard to say something concrete basing on your post because you didn't post constraints that you use. Apple Documentation:

systemLayoutSizeFittingSize:

Returns the size of the view that satisfies the constraints it holds.

Maybe you created constraints that can be interpreted in the way the size of the cell is equal to (0,0).

There is another way you can check the height of the cell with the text. You can put your text in the UITextView and then:

UITextView textView; 
textView.text = @"l";
textView.font = [UIFont fontWithName:FONT_NAME size:FONT_SIZE];
//some code here
//
CGFloat cellHeight = textView.contentSize.height;

It is important to set the text and font (and every other property that can cause the change of the height of the UITextView) of the UITextView before using contentSize property. Also you must first add UITextView to the view.

////// EDIT

The problem with your approach with using constraints can be that you want to measure the cell which ISN'T added to the view so the system don't have all the informations it needs. It doesn't know how much space that will be for the space etc because it doesn't know the surrounding area of the cell

like image 45
Rafał Augustyniak Avatar answered Sep 19 '22 14:09

Rafał Augustyniak