In my application I parsed the data through NSXMLParser and made separate class to store that data from which i usually display the data. Everything works fine in simulator except the the title which is display in table cell with image. Images appears properly but the title not appear properly.
This is my code:-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TableCell3" owner:self options:NULL];
cell = nibLoadedCell;
}
NewsInfo *aNewsInfo = [appDelegate.newsArray objectAtIndex:indexPath.row];
titleLabel.text = aNewsInfo.title;
imageLabel.image = aNewsInfo.smallImageData;
return cell;
}
and in this way i configured my TableCell3.xib
Now i want my title data in 2 rows in label of the TableCell3.
I already used both the way through xib attributes settings or through code.
Code which i used instead of this xib attributes settings are:-
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.text = aNewsInfo.title;
Now Can any one help me to figure out this prob i want to display my title in two rows of the table view cell.
Thanks in Advance.
Just increase the height of your label and give a try. If the height is too less to hold 2 lines, the label will truncate the contents to 1 line and end with the ellipsis.
Shouldn't you be accessing them by
cell.titleLabel.text = sometest;
cell.imageLabel.image = someImage;
and also ensure that the titleLabel and imageLabel are connected properly to the outlets. And pls check your naming for the variables. imageLabel is not a good choice if you want that to be an imageview.
Related
I am attempting to call a reloadData on my table's rows on a viewDidAppear method access. However, my cells are not refreshing their values and I cannot figure out why, as it seems everything is being accessed in the order it is suppose to. To make matters more odd, 1 row actually does refresh, but none of the others do.
Here is my code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Set up the cell...
static NSString *CellWithIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellWithIdentifier];
NSLog(#"generating cell contents");
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellWithIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [_tableGroup.options objectAtIndex:rowcount];
rowcount++;
//label for currently selected/saved setting
_currentSetting = [[UILabel alloc] initWithFrame:CGRectMake(160, 8, 115, 25)];
[_currentSetting setFont:[UIFont systemFontOfSize:14]];
_currentSetting.backgroundColor = [UIColor clearColor];
_currentSetting.textColor = [UIColor blueColor];
_currentSetting.textAlignment = NSTextAlignmentRight;
[cell.contentView addSubview:_currentSetting];
NSLog(#"added new label to cell");
}
//depending on the setting, set the label in the cell to what is currently selected
if (indexPath.section == 1 && indexPath.row == 0) {
_currentSetting.text = [NSString stringWithFormat:#"%# %#",[settings.mapDistance stringValue], NSLocalizedString(#"MILES_IDENTIFIER", nil)];
NSLog(#"setting map distance label: %#", settings.mapDistance);
}
else if(indexPath.section == 1 && indexPath.row == 1)
{
_currentSetting.text = [NSString stringWithFormat:#"%# %#",[settings.maxCustomers stringValue], NSLocalizedString(#"ITEMS_IDENTIFIER", nil)];
NSLog(#"setting max customers: %#", settings.maxCustomers);
}
else if(indexPath.section == 2)
{
_currentSetting.text = [NSString stringWithFormat:#"%# %#",[settings.maxProducts stringValue], NSLocalizedString(#"ITEMS_IDENTIFIER", nil)];
NSLog(#"setting max products: %#", settings.maxProducts);
}
return cell;
}
based on this code, i get this output with my NSLOGS.
this is the first run of the cells when the view is created. It generates 4 cells, puts labels in each cell, and in 3 of those labels, puts in a value.
generating cell contents
added new label to cell
generating cell contents
added new label to cell
setting map distance: 15
generating cell contents
added new label to cell
setting max customers: 250
generating cell contents
added new label to cell
setting max products: 150
at this point i have clicked a row, went to a different screen, and have now returned. as you can see, map distance is different. although no change is displayed, even though the code to change the label's text is accessed during the reload process.
reloading data
generating cell contents
generating cell contents
setting map distance: 25
generating cell contents
setting max customers: 250
generating cell contents
setting max products: 150
again, I'm at a loss because the last row DOES refresh correctly. But none of the others do.
Thanks
When you reload your tableView, the cells already exist and are dequeued from the tableView, so the condition if (cell == nil) returns false, and the cell creation code is not executed.
In that cell creation code, you are assigning a value to _currentSetting and then proceed with the acode assuming that value is correct. However, when the cell creation code is not executed, that value points to the latest created cell, and thus, it won't update.
To fix this: make _currentSetting a local variable and change the code to look like this:
(You don't really need to make it a local variable, but it's more appropriate because you don't really need a reference to the last label you created after you leave this method)
UILabel *_currentSetting = nil;
if (cell == nil) {
_currentSetting = ...
_currentSetting.tag = 123;
}
else
_currentSetting = [cell.contentView viewWithTag:123];
...
The problem here is that the second time (when you are reloading the view ) the _currentSetting is not having a valid memory .So it is better to implement a custom cell and do the job
Better refer this an excellent guide
The second time around, you can see that "added new label to cell" isn't being called, so you're re-using an old tableViewCell.
Note that you're not setting _currentSetting when re-using a cell, only when creating a new cell. So _currentSetting is set to the last new cell that was created, most likely the last cell in the table.
You need to make sure to set _currentSetting to the correct label (maybe by using viewWithTag: or something similar).
(e:f;b)
Brand new poster here on StackOverflow. I've been reading and learning here for some time, but I need to start asking a few questions and interacting, so any help with a few of my issues would be greatly appreciated.
I basically generate a list in a tableView of default sounds from a plist in cellForRowAtIndexPath. This generates me a list of say "x" sounds and one of those sounds has a default checkmark accessory placed on its cell. I have a plist file that stores the 'active' sound file's index value, this is how I put the original checkmark in the generated tableView. So, in the code below, as you can see, I load in the plist's value for the 'active' sounds index, however, when a user interacts with my tableView and they select a new sound, I need the default checkmark placed to be removed from view. Everything else is working fine. I can't seem to crack this simple problem, Im sure its a simple syntax issue, i just don't know how to get it done. Im sure the solution is a single line of code or two and its right under my nose. Thank you for help in advance.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dictionarySound = [NSDictionary dictionaryWithContentsOfFile:[self ActDataFilePath]];
NSNumber *defaultSoundIndex = [dictionarySound valueForKey:#"soundIndex"];
int theIntVal = [defaultSoundIndex integerValue];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Everything below works just fine, checkmarks are removed and placed accordingly, sounds are played just fine. I just need help above in removing the default checkmark
if(self.checkedPath)
{
UITableViewCell *uncheckCell = [tableView cellForRowAtIndexPath:self.checkedPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedPath = indexPath;
....... other code below the plays my sounds on click and stores the newly active sound name and index value in the plist.
The usual way of dealing with this is to use didSelectRowAtIndexPath: to record the fact that the selection has changed and tell the table view to reload data, either all or just for the affected cells, then do the accessoryType configuration in cellAtRowForIndexPath:.
Other ways tend to fail if scrolling of the table is possible.
Alright boys and girls, here is the solution to my own question.
The checkmark is determined and placed in cellForRowAtIndexPath initially when the table is built based on my plist file. Here is the code for my cellForRowAtIndexPath that grabs my plist data, builds my table and sets the default selection with a checkmark.
NSDictionary *dicSound = [NSDictionary dictionaryWithContentsOfFile:[self ActDataFilePath]];
NSNumber *defaultSoundIndex = [dicSound valueForKey:#"soundIndex"];
//conversion of NSNumber to integer for comparison below to indexPath.row, both need to be int's
int theIntVal = [defaultSoundIndex integerValue];
static NSString *CheckMarkCellIdentifier = #"CheckMarkCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CheckMarkCellIdentifier];
cell.textLabel.text = [[MyArray objectAtIndex:indexPath.row] objectForKey:#"name"];
if(indexPath.row == theIntVal)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
When the user interacts with the tableView by clicking on another cell and didSelectRowAtIndexPath kicks in, this is how Im placing the new checkmark and how Im setting the old cell to have no accessory checkmark.
//This is a dictionary file that contains a number of values I need to grab
NSDictionary *dictionarySound = [NSDictionary dictionaryWithContentsOfFile:[self ActDataFilePath]];
NSNumber *defaultSoundIndex = [dictionarySound valueForKey:#"soundIndex"];
//conversion of NSNumber to integer for comparison below to indexPath.row, both need to be int's
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(self.checkedPath)
{
UITableViewCell *uncheckCell = [tableView cellForRowAtIndexPath:self.checkedPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedPath = indexPath;
//THE FIX
[tableView reloadData];
The key here is the [tableView reloadData]; line as it reloads the table with the new options checked and removes the original checkmark. Obviously, Im reloading data which means that I have persistence built in in a plist file. I basically update the local dictionary's value for 'soundIndex' EVERY TIME a user clicks on a cell and then write that to the persistent plist file.
Hope this helps anyone else who is having this issue.
Try following code
cell.accessoryType = UITableViewCellAccessoryNone;
When using the following code to re-size a table row the last line of text is always cutoff, no matter how many lines there are. But there is white space added that looks like enough space for the text.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat restOfTheCellHeight = tableView.rowHeight - cell.detailTextLabel.frame.size.height;
CGSize constrainedSize = CGSizeMake(cell.detailTextLabel.frame.size.width, CGFLOAT_MAX);
CGSize textHeight = [cell.detailTextLabel.text sizeWithFont:cell.detailTextLabel.font constrainedToSize:constrainedSize lineBreakMode:cell.detailTextLabel.lineBreakMode];
CGFloat newCellHeight = (textHeight.height + restOfTheCellHeight);
if (tableView.rowHeight > newCellHeight) {
newCellHeight = tableView.rowHeight;
}
return newCellHeight;
}
Here is the code in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableRowTypeSingleLineValueSmallLabel *cell = (CustomCellTableRowTypeSingleLineValueSmallLabel *)[tableView dequeueReusableCellWithIdentifier:#"CellTypeMultiLineLabelInCellSmallCell"];
if (cell == nil) {
NSArray *xibObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCellTableRowTypeSingleLine" owner:nil options:nil];
for(id currentObject in xibObjects) {
if([currentObject isKindOfClass:[CustomCellTableRowTypeSingleLineValueSmallLabel class]]){
cell = (CustomCellTableRowTypeSingleLineValueSmallLabel *)currentObject;
}
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.editingAccessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.detailTextLabel.numberOfLines = 0;
cell.detailTextLabel.text = self.attributeStringValue;
cell.textLabel.text = self.rowLabel;
return cell;
}
Any ideas?
You need to call [cell.detailTextLabel sizeToFit] in order for the label to actually resize in cellForRowAtIndexPath. It will not resize on its own just because you set numberOfLines to 0. See this question and read its answers for more clarification.
You are calculating the cell height appropriately in your heightForRowAtIndexPAth method, but then in your cellForRowAtIndexPath method you are never actually using it to set the height of your label within it.
So the table is allocating the right amount of space based on your heightForRowAtIndexPath, but then inserting into that space the unresized cell that you return from cellForRowAtIndexPath. I think this might the the cause of the problem and would explain the results you are seeing.
In cellForRowAtIndexPath you need to actually set the height of the label using the same calculation.
i.e.
CGSize constrainedSize = CGSizeMake(cell.detailTextLabel.frame.size.width, CGFLOAT_MAX);
CGRect cframe = cell.detailTextLabel.frame;
cframe.size.height = constrainedSize.height;
cell.detailTextLabel.frame = cframe;
You may also need to actually set the content view frame as well (not sure how it works with a non-custom cell).
I'm also not sure its a good idea to be calling cellForRowAtIndexPath from the heightForRowAtIndexPath method (it would probably be better to just directly access the text data you are using for the size calculation directly).
Turns out I just needed to enable all of the Autosizing options in interface builder for the label.
I'm using a custom UITableViewCell. They load up great, but when they get reused instead of replacing the text in the labels, they are some how writing over the top of them. Any ideas how to stop this behaviour?
I assume I'm not reseting the view correctly before it gets reused. I'm currently empty the labels so they have just a blank #"" string. But I still get the old text plus the new (very messy).
I'm certain there's an obvious solution to this (presently i just don't reuse the cell, but this isn't best practice and is slow on old devices), so if someone can help I'd be very grateful.
Thanks
ED
As requested here is the method for amending the cell
static NSString *CellIdentifier = #"Cell";
TransactionCellView *cell = (TransactionCellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TransactionCellView" owner:self options:nil];
cell = tblCell;
}
[cell resetCell]; // clears the labels
[cell setData:[dataArray objectAtIndex:[indexPath row]]; // replaces the data and updates the labels
return cell;
}
Solved this issue!!! Amazingly simple when you know what the problem is/was.
I was using IB and "Clear Graphics Context" was not selected on my UILabels. So that is why the next text was just overlaying the old.
THanks guys for trying to help.
I suspect that you are adding the label as a subview programatically in your cellForRowAtIndexPath method. You need to make sure that you are not adding that subview every time the cell is recycled. Instead create the label only when creating a new cell (not when recycling a cell) then assign a tag value to the label and then in the future, when it gets recycled, retrieve the label by tag value and change its text.
You are correct in that the cells are being reused. Your code should be set up roughly using the following pattern:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* identifier = #"someidentifier";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(!cell) {
// create the cell and add all subviews to it
} else {
// update the cell and access appropriate subviews to modify what is displayed
}
return cell;
}
The cell will be created the first time the identifier is used. For all subsequent requests, the cell is pulled from the UITableView cache (via dequeueReusableCellWithIdentifier), and you can then access its subviews either by tag, index, type, or whatever mechanism you choose.
Somewhat related is that you can have multiple cell identifiers, which allows you to create multiple instances of different cells depending on the data that you have. In one of my projects, I have 4 different cells, each dependent upon the number of lines of data that they will display (anywhere between 1 and 4). This helps ensure a smooth scrolling experience regardless of how many lines the cell has since the renderer doesn't have to worry about dynamically changing the height of the cell on the fly.
Try this..
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
for (UIView* subView in cell.contentView.subviews)
{
[subView removeFromSuperview];
}
// Your Code to customize cell goes here.
}
In my application I parsed the data through NSXMLParser and made separate class to store that data from which i usually display the data. Everything works fine in simulator except the the title which is display in table cell with image. Images appears properly but the title not appear properly.
This is my code:-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TableCell3" owner:self options:NULL];
cell = nibLoadedCell;
}
NewsInfo *aNewsInfo = [appDelegate.newsArray objectAtIndex:indexPath.row];
titleLabel.text = aNewsInfo.title;
imageLabel.image = aNewsInfo.smallImageData;
return cell;
}
and in this way i configured my TableCell3.xib
Now i want my title data in 2 rows in label of the TableCell3.
I already used both the way through xib attributes settings or through code.
Code which i used instead of this xib attributes settings are:-
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.text = aNewsInfo.title;
Now Can any one help me to figure out this prob i want to display my title in two rows of the table view cell.
Thanks in Advance.
My Data is showing in this way...![enter image description here][2]
So i want to display this title fully it show's partially right now...
i want to display in two lines...
My guess is that you need to enlarge the label height.
Maybe the label height i not large enough to display 2 lines of text and that's could be the reason that you see only 1 line.
in interface builder try to enlarge the label height.
and maybe i am wrong ?
Good luck
Shani
Adjust frame of an UiLabel to have more space for two lines or decrease font size.