Set different height for two custom UITableViewCell - ios

I have two custom UITableViewCell in my table view, that I can't resize properly. The problem is that in IB there is a row height option for the table view, that sets the same height for both cells. I can't just edit the height of the cells in IB, somewhy it doesn't works, the table view's row height overwrites it. I'm using static heights so I tried to set it based on the cell's type, but can't make it work. Is it possible that just my if statement is wrong or I done the whole thing wrong?
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath {
InboxCellTableViewCell *cellMessage = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
InboxCell2TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell2" forIndexPath:indexPath];
if(cell) {
[cellMessage layoutIfNeeded];
return 200;
} else {
[cell layoutIfNeeded];
return 155;
}
}

You definitely can do this, and you will do it in -heightForRowAtIndexPath as you suspect.
Instead of attempting to load the cell as you are doing, you should instead use the IndexPath to determine what type of cell is there and then return the proper height for that cell type.
In your cellForRowAtIndexPath method you must have some logic that is already determining the cell type for a given IndexPath, as you return a varying type of Cell from that method already? That same logic can be used to return the appropriate height in the heightForRowAtIndexPath method.

Related

How to get a cell without calling cellForRowAtIndexPath in objective C iOS?

We can get a cell from:
UITableViewCell * cell = [self tableView:tableVie cellForRowAtIndexPath:indexPath]
but it will calling the method cellForRowAtIndexPath:
if I know the cell's tag or indexPath , it's there a way to get the specified cell without to calling cellForRowAtIndexPath:?
Add some reason why I can't call cellForRowAtIndexPath:indexPath
I want to get the cell in the method cellForHeightAtIndexPath to reset the height of each cell. :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CommentsListResponseDataModel * model = self.liveCommentData[indexPath.row -1];
if (model.viewHeight > 0) {
return model.viewHeight;
} else {
if (model.parentComment) {
CommentParentCell * cc = (CommentParentCell *)cell;
return cc.viewHeight;
} else {
CommentSingleCell * cc = (CommentSingleCell *)cell;
return cc.viewHeight;
}
}
}
}
But this will become a dead loop because it all cellForRowAtIndexPath:indexPath and cellForRowAtIndexPath:indexPath will recall cellForHeightAtIndexPath:indexPath
As of my understanding, you are trying to get the cell object by calling UITableView datasource method. But when you try to do like that then it will be infinite loop call and you will never get the cell object. So in order to get cell object from UITableView, do the following steps.
Declare your UITableView as global to the your ViewController, something like UITableView *_tableView; or #IBOutlet weak UITableView *_tableView;
Then try to call the
//specify the item indexpath
NSIndexPath *_indexPath = [NSIndexPath indexPathForItem:3 inSection:1];
//now try to access cell object by passing cell indexPath
UITableViewCell *_cell = [_tableView cellForRowAtIndexPath:_indexPath];
It seems you want something unrelated to your original question - you want your table view cells to size automatically, depending on content.
What you need to do is:
1. add constraints to your cell - make sure it doesn't have a height constraint, but its content must have Top and Bottom constraints.
2. remove heightForRowAtIndexPath as it will not be necessary
3. set your table view row height to automatic
tableView.rowHeight = UITableViewAutomaticDimension
Now just setup your cell - resize its content to desired height and table cell will automatically be resized

How to determine UIWebView height based on content inside a variable height UITableView?

I have a UITableView cell that is going to have a variable size depending on it's content (potentially several lines of text).
Since it appears that heightForRowAtIndexPath is called before I layout the cell, I just guess the correct height by calling [NSString sizeWithFont] on my text string. Is there a better way to set the height after I've laid out the text in the cell and have an idea of exactly what size it should be?
My problem is each cell contains a UIWebView with different (statically loaded) content I can't figure out how to calculate the proper height based on the content. Is there a way to do this? I've tried things like this:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewCell *cell = (WebViewCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
[cell setNeedsLayout];
[cell layoutIfNeeded];
return cell.bounds.size.height;
}
The cells themselves are loaded from a nib, which is simply a UITableViewCell containing a UIWebView. (It would also be fine if the cells just adjusted themselves to the largest of the html content, though variable height would be nicer).
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath {
UITableViewCell *cell = [self tableView: tableView cellForRowAtIndexPath: indexPath];
return cell.bounds.size.height;
}

Change height of a swiped tableview cell on height

I have a standard tableview of .Subtitle style. However, I would like to show the detailed text only when the cell is swiped. I would like to increase the height of the swiped cell (and only the swiped cell) to display the detailed text. I have not tried creating 2 cell prototypes and swapping the cell on the swipe and I am not experienced enough to implement it. I could implement the optional function heightForRowAtIndexPath but that would change every cell unconditionally.
I would appreciate any ideas on how to do this.
In tableViewheightForRowAtIndexPath method, you could change specific cell height, and keep other cells in the same height.
you can check the below sample code
NSIndexPath *selectedCellIndexPath;
//
- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectedCellIndexPath = indexPath;
// Forces the table view to callheightForRowAtIndexPath
[tableView reloadRowsAtIndexPaths:[NSArrayarrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationNone];
}
- (CGFloat)tableView:(UITableView *)tableViewheightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Note: Some operations like calling [tableViewcellForRowAtIndexPath:indexPath]
// will call heightForRow and thus create astack overflow
if(selectedCellIndexPath != nil
&& [selectedCellIndexPathcompare:indexPath] == NSOrderedSame)
return 64;
return 32;
}

Access custom cell properties in heightForRowAtIndexPath

I have a custom UITableViewCell. I want to access the cells properties i.e. a UILabel etc. I tried inserting the following code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CategorieCell *customCell = (CategorieCell *)[tableView cellForRowAtIndexPath:indexPath];
return ...
}
When I run the app, it crashed without giving me error details. The problem is with the new customCell I'm creating. Is there another way I can access the customCell.m objects?
About the crash, please note that you are using cellForRowAtIndexPath: wich is a method from the UITableViewDatasource that you have to implement, this method calls heightForRowAtIndexPath by default, so it will become a recursive
I assume that you want your custom cell in this method in order to get the height from it.
The best way to achieve this is write a class method on CategorieCell that gives you the height for a cell with certain data.
Other option is extract a method with the code to get the uitableviewcell for example
(CategorieCell*) categorieCellForIndex:(NSIndex)index selected:(BOOL)selected{
...
}
In heightForRowAtIndexPath should never be called cellForRowAtIndexPath.
The first one is called before the second one, and if you need to access to a label (for example to calculate the height of the text) you can normally init a cell.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static CategorieCell *cell;
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
cell.frame = CGRectMake(0, 0, tableView.frame.size.width-tableView.contentInset.left-tableView.contentInset.right, cell.frame.size.height);
[cell layoutIfNeeded];
}
cell.label.text = myDatasourceText;
CGFloat cellHeight = ....
return cellHeight;
}
NOTE 1:
I used dequeueReusableCellWithIdentifier supposing you are using Interface Builder, otherwise you need to use alloc] initWithStyle:...];
NOTE 2:
As you see I'm setting the frame of the cell. This is needed because otherwise your cell will be (320 x 44) as default. You instead could be in iPhone 6/6+ (i.e. screen width: 414) or in an iPad, and you could need to calculate an height of a label according with his width and his text, and for this reason you need to set the frame of the cell.
NOTE 3:
I'm assuming you have a set of equal cell structure, and for this reason I'm using a static cell, so it will be reused without allocate other useless cells.
Try to register your custom cell class like so:
[self.tableView registerClass:[CategorieCell class] forCellReuseIdentifier:NSStringFromClass([CategorieCell class]);
and then in -tableView:heightForRowAtIndexPath: do something like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CategorieCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CategorieCell class)];
}

Calculate custom UITableViewCell height at "indexPath" from -tableView:cellForRowAtIndexPath:?

I adjust the height of a custom UITableViewCell inside the custom class, and I believe I need to use the -tableView:cellForRowAtIndexPath: method to adjust the height of the cell. I am attempting to just adjust the height of the custom cell in the custom cell class, then grab the cell at the given index path cast it, and return the height of that cell like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CustomUITableViewCell *cell = (CustomUITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
return cell.frame.size.height;
}
But I am getting stack overflow. What is a better way around doing this?
The table view delegate will first call heightForRowAtIndexPath: and then the datasource will construct the cell in cellForRowAtIndexPath: after that based on the computed information.
Therefore your approach will not work.
You need to have some logic for computing the height. (E.g. if you are displaying text the height might be dynamic and depend on the amount of text - you could calculate that with an NSString method.)
If you are just displaying a few types of cells with fixed heights, simply define these heights as constants and return the correct height based on the same logic you have in cellForRowAtIndexPath: to decide which cell to use.
#define kBasicCellHeight 50
#define kAdvancedCellHeight 100
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (needToUseBasicCellAtThisIndexPath) {
return kBasicCellHeight;
}
return kAdvancedCellHeight;
}
If it's a storyboard cell, you can call dequeueReusableCellWithIdentifier:. Otherwise, you can just instantiate the cell directly with something like [CustomUITableViewCell alloc] initWithFrame:].
I use this approach (using a prototype cell to calculate height) myself because it allows our designer to modify storyboard cells without requiring code changes.
You may want to adjust your approach based on whether the height is static or dynamic as discussed here.

Resources