Table View troubles with dequeue cell - ios

So I am having trouble showing my data in a UITableView. I do believe it has something to do with reusing the cells. I have checked online and here at SO but have not found a solution that works for me. Any help would be appreciated.
I have an Array that is populated by text and pictures. I am then showing the information in a tableView. If I were to use static sized cells everything works out fine, but the amount of text changes, so I have also implemented the heightForRowAtIndexPath method. This works as well, until I scroll all the way down to the bottom.
After that, when I scroll back up, all the cell heights change and the display gets all jumbled. Some text gets cut off, pictures get chopped and some of the cells only have the last portion of text. I really think it has something to do with reusing the cells, but I don’t know how to attack this problem. Below is my code for cellForRowAtIndexPath and heightForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSString *label = [_theBigArray objectAtIndex:indexPath.row];
CGSize stringSize = [label sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
UITextView *textV = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height +50)];
textV.font = [UIFont systemFontOfSize:15];
textV.text = [_theBigArray objectAtIndex:indexPath.row];
textV.textColor = [UIColor blackColor];
textV.editable = NO;
[cell.contentView addSubview:textV];
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 290, 100)];
imageV.contentMode = UIViewContentModeScaleAspectFit;
imageV.image = [_theBigArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageV];
}
return cell;
[tableView reloadData];
}
For heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
int rowHeight = 0.0f;
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSString *temp = [_theBigArray objectAtIndex:indexPath.row];
CGSize size = [temp sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
rowHeight = size.height+50;
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
rowHeight = 115.0f;
}
//NSLog(#"rowHeight is %i", rowHeight);
return rowHeight;
[tableView reloadData];
}
I even tried to make two different cells and call them separately, but the same thing happens. I did still use the same heightForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *newCell = [[UITableViewCell alloc] init];
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
NSString *label = [_theBigArray objectAtIndex:indexPath.row];
CGSize stringSize = [label sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
UITextView *textV = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height +50)];
textV.font = [UIFont systemFontOfSize:15];
textV.text = [_theBigArray objectAtIndex:indexPath.row];
textV.textColor = [UIColor blackColor];
textV.editable = NO;
[cell.contentView addSubview:textV];
newCell = cell;
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PictureCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"PictureCell"];
}
UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 290, 100)];
imageV.contentMode = UIViewContentModeScaleAspectFit;
imageV.image = [_theBigArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageV];
newCell = cell;
}
return newCell;
[tableView reloadData];
}
Any ideas?

The main problem is that you're adding subviews to cells every time they scroll in, but when a cell is reused, it will already have those subviews added. (That is, when a cell is reused, it will already have a UITextView or UIImageView depending on the reuse identifier.)
You need to check if these subviews exist first; this is commonly done by using the -[UIView viewWithTag] method, or by subclassing UITableViewCell and assigning each view as a property.
(You can take a look at the SO question How to get other control value from UITableViewCell? to see how to use viewWithTag. I would avoid subclassing UITableViewCell until you're more comfortable with the out-of-the-box implementation.)
Also, this line of code:
UITableViewCell *newCell = [[UITableViewCell alloc] init];
is a terrible idea, because you are creating a new UITableViewCell without checking to see if you can reuse one first. This defeats the entire purpose of reusing cells, which is fast scrolling performance. Instead, just declare it without initializing it:
UITableViewCell *newCell;
Also, in heightForRowAtIndexPath, you are
declaring rowHeight as an int (it should be a CGFloat)
trying to call reloadData after the method returns (which will never happen, but you should never try to call reloadData from this method)

Related

Adding UILabel in custom cell issue

I have custom cell in my UITableView and according to the string's value I want to add a UILabel in the cell.
Here is my code for cell,
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary * tmpDictn = [tableAry objectAtIndex:indexPath.section];
NSString * typeStr = [tmpDictn objectForKey:#“DocumentType”];
NSString * cellIdentifier = #"TestCell";
TestCell *cell = (TestCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){
cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if ([typeStr isEqualToString:#“Text”]) {
UILabel * textLbl = [[UILabel alloc] init];
textLbl.backgroundColor=[UIColor clearColor];
textLbl.textColor=[UIColor lightGrayColor];
textLbl.userInteractionEnabled=NO;
textLbl.numberOfLines = 0;
textLbl.font = [UIFont fontWithName:#“Helvetica" size:16];
[textLbl setFrame:CGRectMake(30, 20, 250, 25)];
textLbl.text= [NSString stringWithFormat:#"%# %i",[splitAry objectAtIndex:i],indexPath.section];
[cell addSubview:textLbl];
}
}
return cell;
}
My UITableView contain 5 cell(dynamic). And only first cell should have this label(this also change according to Text). This code is adding UILabel in first cell but also add UILabel at 3 and 5th cell.
I have checked that its same UILabel created 1 time and added in cell 1st, 3rd and 5th. And "Text" is only at first position in Tableary.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary * tmpDictn = [tableAry objectAtIndex:indexPath.section];
NSString * typeStr = [tmpDictn objectForKey:#“DocumentType”];
NSString * cellIdentifier = #"TestCell";
TestCell *cell = (TestCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){
cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
UILabel *lbl = [cell viewWithTag:1];
if(lbl)
{
[lbl removeFromSuperView];
}
if ([typeStr isEqualToString:#“Text”]) {
UILabel * textLbl = [[UILabel alloc] init];
textLabel.tag = 1;
textLbl.backgroundColor=[UIColor clearColor];
textLbl.textColor=[UIColor lightGrayColor];
textLbl.userInteractionEnabled=NO;
textLbl.numberOfLines = 0;
textLbl.font = [UIFont fontWithName:#“Helvetica" size:16];
[textLbl setFrame:CGRectMake(30, 20, 250, 25)];
textLbl.text= [NSString stringWithFormat:#"%# %i",[splitAry objectAtIndex:i],indexPath.section];
[cell addSubview:textLbl];
}
}
return cell;
}
Try using a different cell identifier for the cells that need a label added to them, e.g. #"TextCell". Otherwise, you are reusing cells that already have a label added even if it is not supposed to be there. Alternatively, you could remove the label (if it is there) in an 'else' condition of your if ([typeStr isEqualToString:#“Text”]) block but I think that the former is cleaner.
You are using
[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
The problem for your code is that table view is reusing your cell. So it will appear in many as your number of cells increases.
I am a bit old programmer but I think the best way is to
if (!cell)
{
cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
//Add your label here.
}
if(!label)
{ //your code;
//set label text to nil if your condition not met;
}
A quick solution for you is to put an else and set text to nil;
Cheers.

How to disable reloading tableview when scrolling in iOS

I want to disable reloading table view when scrolling. Now, my app when user scroll the uitableview, cellForRowAtIndexPath has been recalled. How can I disable it when srcolling? Please give me some advice. Thanks in advance.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%d,%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *FileNameLabel;
UILabel *UploadTimeLabel;
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
CFileNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 0, 130, 30)];
UploadTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 20, 130, 25)];
FileNameLabel.tag = 1000;
FileNameLabel.backgroundColor = [UIColor clearColor];
FileNameLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
FileNameLabel.font = [UIFont boldSystemFontOfSize:14];
FileNameLabel.textColor = [UIColor blackColor];
// FileNameLabel.text =[temp objectAtIndex:indexPath.row];
[cell.contentView addSubview: FileNameLabel];
[FileNameLabel release];
UploadTimeLabel.tag = 2000;
UploadTimeLabel.backgroundColor = [UIColor clearColor];
UploadTimeLabel.font = [UIFont fontWithName:#"Helvetica" size:12];
UploadTimeLabel.textColor = [UIColor grayColor];
// UploadTimeLabel.text = [UploadTimeArray objectAtIndex:indexPath.row];
[cell.contentView addSubview: UploadTimeLabel];
[UploadTimeLabel release];
}
if( [OriginalArray count] > 0)
{
UILabel *fileNameLbl = (UILabel*)[cell.contentView viewWithTag:1000];
//fileNameLbl.text =[temp objectAtIndex:indexPath.row];
fileNameLbl.text =[[OriginalArray valueForKey:#"FILENAME"] objectAtIndex:indexPath.row];
UILabel *uploadlbl = (UILabel*)[cell.contentView viewWithTag:2000];
uploadlbl.text =[[OriginalArray valueForKey:#"UPLOADTIME"] objectAtIndex:indexPath.row];
}
_tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
return cell;
}
You cannot block the cellForRowAtIndexPath: from calling when scrolling the tableview. If something need not happen every time, You may keep it in if condition.
if (cell == nil)
{
//Functionality goes here when it not needed to happen every time.
}
Do not implement the method UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"yourID"]; or UITableViewCell *cell = [tableView dequeueCellWithReuseIdentifier:nil];
It will prevent the table view from reusing the cell. But its not a good idea if your tableview is going to contain large number of cell. Hope this helps. :)
Instead of trying to avoid being reloaded, maybe you could play with your data source, so that it appears as the data doesn't change. I hope you understand what I mean.
use dequecellforrowatindex method to avoid cell reloading.

How to set two array data in one cell content of custom tableview in ios?

hello I am beginner in iOS I have created custom table view and I have Two array then I want to set both array data together in simultaneously one by one cell content in table view I show image which i want..
Please refer : http://i.stack.imgur.com/WIkaf.png
NSMutableArray *SearchPatientCode;
NSMutableArray *SearchPatientName;
UITableView *table_SearchPatient;
SearchPatientCode=[[NSMutableArray alloc]initWithObjects:#"PH230130420",#"PH230420321",#"Ph450362120", nil];
SearchPatientName=[[NSMutableArray alloc]initWithObjects:#"Rahul Sharma",#"Amit kumar",#"anil sharma", nil];
table_SearchPatient=[[UITableView alloc]initWithFrame:CGRectMake(130,40,170,250)style:UITableViewStylePlain];
table_SearchPatient.delegate=self;
table_SearchPatient.dataSource=self;
table_SearchPatient.layer.borderWidth = 2.0;
table_SearchPatient.layer.borderColor = [UIColor grayColor].CGColor;
[self.view addSubview:table_SearchPatient];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(tableView==table_SearchPatient)
{
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
cell.textLabel.text =[NSString stringWithFormat:#"%# /n %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:10.0f];
// cell.detailTextLabel.text=[SearchPatientName objectAtIndex:indexPath.row];
}
return cell;
}
I am using this But this is not show as I want ...Solve this problem!!
Add New UILable with numberOfLines = 2 like bellow...
if you want to unlimited line with your content data then you can do it with set numberOfLines = 0 and set lineBreakMode = UILineBreakModeWordWrap
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(tableView==table_SearchPatient)
{
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
UILabel *lbl = [[UILabel alloc]init];
lbl.text = [NSString stringWithFormat:#"%# /n %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]];
lbl.font = [UIFont fontWithName:#"Helvetica-Bold" size:10.0f];
[lbl setFrame:CGRectMake(20, 2, 250, 35)];// set frame which you want
[lbl setBackgroundColor:[UIColor clearColor]];// set any color here
// lbl.lineBreakMode = UILineBreakModeWordWrap; // set it if you want to height of UILable with its content (Multiple line)
lbl.numberOfLines = 2;// Add this line // Set 0 if you want to multiple line.
[cell.contentView addSubview:lbl];
}
return cell;
}
You can use detail cell.detailTextLabel.text.
Or You can create a custom cell and add the labels to the cell like this
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
cell.textLabel.text = #"";
label_name_one = [[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 90, 20)]autorelease];
[label_name_one setText:[SearchPatientCode objectAtIndex:indexPath.row]];
label_name_two = [[[UILabel alloc]initWithFrame:CGRectMake(92, 30, 170, 80)]autorelease];
[label_name_two setText:[SearchPatientCode objectAtIndex:indexPath.row]];
set the RectFrame according to your requirements.
Firstly change your cell style as UITableViewCellStyleValue2 then Use this code for multiline text in cell :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cellIdentifier = #"MyIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2
reuseIdentifier:cellIdentifier];
[[cell textLabel] setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0f]];
}
[[cell detailTextLabel] setText:[NSString stringWithFormat:#"%# %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]]];
cell.detailTextLabel.numberOfLines = 2;
cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
Hope it helps you.
Also make sure you check out the free Sensible TableView framework. Given the arrays, the framework will automatically display all the values in the table view, and will even generate detail views where applicable. Saves me tons of time.

UILabel height inside UITableViewCell

I'm trying to create a tableview where the height of the cells are dynamic.
So far I manage to set the height of the cells depending on the custom UILabel I've added inside.
With the regular cell.textLabel it works fine, but when I use my own label something goes wrong. I only see half the label, but when I scroll up and down, sometimes the label extends and shows all the text... You can see where the label should end in the image.
Image
This is the text inside the cellForRowAtIndexPath:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
Car *carForCell = [cars objectAtIndex:indexPath.row];
UILabel *nameLabel = [[UILabel alloc] init];
nameLabel = (UILabel *)[cell viewWithTag:100];
nameLabel.numberOfLines = 0;
nameLabel.text = carForCell.directions;
[nameLabel sizeToFit];
[nameLabel setBackgroundColor:[UIColor greenColor]];
return cell;
Unless you have typos in the code you posted, you don't seem to be adding the label to the cell at all. You also seem to be creating a new label every time, and then replacing the contents of your nameLabel pointer with the cell's view (which will always be nil).
Try doing something like this first and then see how it looks:
static NSString *CellIdentifier = #"Cell";
UILabel *nameLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
nameLabel = [[UILabel alloc] init];
nameLabel.tag = 100;
nameLabel.numberOfLines = 0;
[nameLabel setBackgroundColor:[UIColor greenColor]];
[cell.contentView addSubview:nameLabel];
}
else {
nameLabel = (UILabel *)[cell viewWithTag:100];
}
// Configure the cell.
Car *carForCell = [cars objectAtIndex:indexPath.row];
nameLabel.text = carForCell.directions;
[nameLabel sizeToFit];
return cell;
You will also need to tell the tableView what size each cell needs to be using the tableView:heightForRowAtIndexPath: delegate method. That will mean getting the relevant Car object again and calculating the height using sizeWithFont:sizeWithFont:forWidth:lineBreakMode:
How are you setting the height of the cell? It should be done in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
You should calculate and return the height of the UITableViewCell in the following method:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
Here you should do your initial calculation of how high your cell should be.
For example:
CGSize textSize = [myString sizeWithFont:[UIFont systemFontOfSize:16] constrainedToSize:CGSizeMake(320, 9999)];
return textSize.height;

How do I wrap text in a UITableViewCell without a custom cell

This is on iPhone 0S 2.0. Answers for 2.1 are fine too, though I am unaware of any differences regarding tables.
It feels like it should be possible to get text to wrap without creating a custom cell, since a UITableViewCell contains a UILabel by default. I know I can make it work if I create a custom cell, but that's not what I'm trying to achieve - I want to understand why my current approach doesn't work.
I've figured out that the label is created on demand (since the cell supports text and image access, so it doesn't create the data view until necessary), so if I do something like this:
cell.text = #""; // create the label
UILabel* label = (UILabel*)[[cell.contentView subviews] objectAtIndex:0];
then I get a valid label, but setting numberOfLines on that (and lineBreakMode) doesn't work - I still get single line text. There is plenty of height in the UILabel for the text to display - I'm just returning a large value for the height in heightForRowAtIndexPath.
Here is a simpler way, and it works for me:
Inside your cellForRowAtIndexPath: function. The first time you create your cell:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:17.0];
}
You'll notice that I set the number of lines for the label to 0. This lets it use as many lines as it needs.
The next part is to specify how large your UITableViewCell will be, so do that in your heightForRowAtIndexPath function:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = #"Go get some text for your cell.";
UIFont *cellFont = [UIFont fontWithName:#"Helvetica" size:17.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 20;
}
I added 20 to my returned cell height because I like a little buffer around my text.
Updated Tim Rupe's answer for iOS7:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:17.0];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = #"Go get some text for your cell.";
UIFont *cellFont = [UIFont fontWithName:#"Helvetica" size:17.0];
NSAttributedString *attributedText =
[[NSAttributedString alloc]
initWithString:cellText
attributes:#
{
NSFontAttributeName: cellFont
}];
CGRect rect = [attributedText boundingRectWithSize:CGSizeMake(tableView.bounds.size.width, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
return rect.size.height + 20;
}
A brief comment / answer to record my experience when I had the same problem. Despite using the code examples, the table view cell height was adjusting, but the label inside the cell was still not adjusting correctly - solution was that I was loading my cell from a custom NIB file, which happens after the cell height in adjusted.
And I had my settings inside the NIB file to not wrap text, and only have 1 line for the label; the NIB file settings were overriding the settings I adjusted inside the code.
The lesson I took was to make sure to always bear in mind what the state of the objects are at each point in time - they might not have been created yet! ... hth someone down the line.
If we are to add only text in UITableView cell, we need only two delegates to work with (no need to add extra UILabels)
1) cellForRowAtIndexPath
2) heightForRowAtIndexPath
This solution worked for me:-
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:16];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
cell.textLabel.text = [mutArr objectAtIndex:indexPath.section];
NSLog(#"%#",cell.textLabel.text);
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow.png" ]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize labelSize = CGSizeMake(200.0, 20.0);
NSString *strTemp = [mutArr objectAtIndex:indexPath.section];
if ([strTemp length] > 0)
labelSize = [strTemp sizeWithFont: [UIFont boldSystemFontOfSize: 14.0] constrainedToSize: CGSizeMake(labelSize.width, 1000) lineBreakMode: UILineBreakModeWordWrap];
return (labelSize.height + 10);
}
Here the string mutArr is a mutable array from which i am getting my data.
EDIT :- Here is the array which I took.
mutArr= [[NSMutableArray alloc] init];
[mutArr addObject:#"HEMAN"];
[mutArr addObject:#"SUPERMAN"];
[mutArr addObject:#"Is SUPERMAN powerful than HEMAN"];
[mutArr addObject:#"Well, if HEMAN is weaker than SUPERMAN, both are friends and we will never get to know who is more powerful than whom because they will never have a fight among them"];
[mutArr addObject:#"Where are BATMAN and SPIDERMAN"];
Now the tableviews can have self-sizing cells. Set the table view up as follows
tableView.estimatedRowHeight = 85.0 //use an appropriate estimate
tableView.rowHeight = UITableViewAutomaticDimension
Apple Reference
I use the following solutions.
The data is provided separately in a member:
-(NSString *)getHeaderData:(int)theSection {
...
return rowText;
}
The handling can be easily done in cellForRowAtIndexPath.
Define the cell / define the font and assign these values to the result "cell".
Note that the numberoflines is set to "0", which means take what is needed.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIFont *cellFont = [UIFont fontWithName:#"Verdana" size:12.0];
cell.textLabel.text= [self getRowData:indexPath.section];
cell.textLabel.font = cellFont;
cell.textLabel.numberOfLines=0;
return cell;
}
In heightForRowAtIndexPath, I calculate the heights of the wrapped text.
The boding size shall be related to the width of your cell. For iPad this shall be 1024.
For iPhone en iPod 320.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIFont *cellFont = [UIFont fontWithName:#"Verdana" size:12.0];
CGSize boundingSize = CGSizeMake(1024, CGFLOAT_MAX);
CGSize requiredSize = [[self getRowData:indexPath.section] sizeWithFont:cellFont constrainedToSize:boundingSize lineBreakMode:UILineBreakModeWordWrap];
return requiredSize.height;
}
I found this to be quite simple and straightForward :
[self.tableView setRowHeight:whatEvereight.0f];
for e.g. :
[self.tableView setRowHeight:80.0f];
This may or may not be the best / standard approach to do so, but it worked in my case.
Try my code in swift . This code will work for normal UILabels also.
extension UILabel {
func lblFunction() {
//You can pass here all UILabel properties like Font, colour etc....
numberOfLines = 0
lineBreakMode = .byWordWrapping//If you want word wraping
lineBreakMode = .byCharWrapping//If you want character wraping
}
}
Now call simply like this
cell.textLabel.lblFunction()//Replace your label name
I think this is a better and shorter solution. Just format the UILabel (textLabel) of the cell to auto calculate for the height by specifying sizeToFit and everything should be fine.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
cell.textLabel.text = #"Whatever text you want to put here is ok";
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell.textLabel sizeToFit];
return cell;
}
I don't think you can manipulate a base UITableViewCell's private UILabel to do this. You could add a new UILabel to the cell yourself and use numberOfLines with sizeToFit to size it appropriately. Something like:
UILabel* label = [[UILabel alloc] initWithFrame:cell.frame];
label.numberOfLines = <...an appriate number of lines...>
label.text = <...your text...>
[label sizeToFit];
[cell addSubview:label];
[label release];

Resources