Can’t set UITableViewCell detailTextLabel.text - iphone

The detailTextLabel is not displayed out accordingly thought the source is there. The textLable.text is displayed accordingly though.
- (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...
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"favouriteListArray"] != nil) {
NSArray *listArray = [NSArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"favouriteListArray"]];
NSLog(#"listArray:%#", listArray);
NSDictionary *listDic = [listArray objectAtIndex:indexPath.row];
NSLog(#"listDic:%#", listDic);
cell.textLabel.text = [listDic objectForKey:#"Description"];
cell.detailTextLabel.text = [listDic objectForKey:#"Address"];
}
return cell;
}
NSLogs of listDic
listDic:{
Address = myAddress;
Description = myDescription;
}

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
You need to use initWithStyle:UITableViewCellStyleSubtitle

Swift (3)
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier")

Related

UITableView redraw issue on scrolling

I have a grouped UITableView that I populate from a list.
On some rows I don't want to have disclosure and on some I need to add label.
But is somehow mix something and add labels on wrong rows and display disclosures at each row.
What am I doing wrong here?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"customdisclosure.png" ]];
}
NSDictionary *dictionary = [_list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Items"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
if([cell.textLabel.text isEqualToString:#"with label"])
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.detailTextLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.text = #"label...";
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else if([cell.textLabel.text isEqualToString: #"No disclosure" ])
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
in your else if clause, you are not clearing the cell.detailTextLabel's text on the reused cell. Set it to nil and you will be fine.
cell.detailTextLabel.text = nil;
You will also need to hide the accessoryView in the else if clause, and unhide it.
cell.accessoryView.hidden = YES;
Overall, I would consider subclassing UITableViewCell so you can override prepareForReuse to reset your cell for the next cellForRowAtIndexPath call.
Guess the issue is with using reusable identifiers. Use different cell identifiers for the cells you do not want accessoryView.
static NSString *CellWithDisclosure = #"CellID_WithDisclosure";
static NSString *CellWithNoDisclosure = #"CellID_NoDisclosure";
NSDictionary *dictionary = [_list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Items"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
if([cell.textLabel.text isEqualToString:#"with label"])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellWithDisclosure];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else if([cell.textLabel.text isEqualToString: #"No disclosure" ])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellWithNoDisclosure];
cell.accessoryType = UITableViewCellAccessoryNone;
}
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID] autorelease];
}
cell.textLabel.text = cellValue;
return cell;

Problem with how UITableViewCell is created by UITableView on reloadData

I know there's similar questions to this, but the approved answers don't seem to be working for me. So, my scenario is that I have a UITableView and I want to add and remove items by scanning a bar code. All that works fine except I can't get the UITableView to display the updated information. The problem specifically comes from the tableView:cellForRowAtIndexPath: method on every other reload after the initial one. More specifically the cell is always not nil, so it skips over the new cell creation logic.
For other questions like mine, the answer is that the cell identifier is the problem. Well, I tried messing around with that and it didn't work. Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if (indexPath.section < vehicle.inventoryCategoriesCount) {
cell = [tableView dequeueReusableCellWithIdentifier:#"ModelCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"ModelCell"] autorelease];
NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category == %#", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:#"#distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];
cell.textLabel.text = model;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"model == %#", model]] count]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"RemoveCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"RemoveCell"] autorelease];
cell.textLabel.text = #"Remove an Item";
cell.textLabel.textColor = [UIColor redColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
return cell;
}
So, in this example code, I have two different cell identifiers for the separate sections. They are ModelCell and RemoveCell. Well, they don't work as a solution because nothing happens. If I change the cell identifier when I'm allocating a new cell it works because it's simply wiping everything since the identifiers don't match, but I'm going to assume that that is wrong and that there should be a better solution to this issue or I'm simply not doing something right.
I'd appreciate some help on this. I've spent a day on this chunk of code so far and I have not gotten anywhere and I'd like to get it fixed and move on to other part of my app...
Thanks in advance for any help!
UPDATE
Thanks to #fluchtpunkt the problem has been resolved. For anyone else who may run into this in the future, here's the corrected code. I decided to make the identifier even more unique by appending the section number to it.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if (indexPath.section < vehicle.inventoryCategoriesCount) {
NSString *identifier = [NSString stringWithFormat:#"ModelCell-%d", indexPath.section];
cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category == %#", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:#"#distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];
cell.textLabel.text = model;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"model == %#", model]] count]];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"RemoveCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"RemoveCell"] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.textColor = [UIColor redColor];
}
cell.textLabel.text = #"Remove an Item";
}
return cell;
}
UPDATE
The final code version which corrects my misunderstanding of how the identifier works. I figured I'd keep it simple, so I named the identifiers after the cell style type.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if (indexPath.section < vehicle.inventoryCategoriesCount) {
cell = [tableView dequeueReusableCellWithIdentifier:#"Value1"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Value1"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category == %#", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:#"#distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];
cell.textLabel.text = model;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"model == %#", model]] count]];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"Default"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Default"] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.textColor = [UIColor redColor];
}
cell.textLabel.text = #"Remove an Item";
}
return cell;
}
put your cell configuration outside of if (cell == nil) { ... } The if condition is only true if no cell could be reused. And you definitely want to reuse your cells. So configure them when you have a valid cell.
Like this:
if (indexPath.section < vehicle.inventoryCategoriesCount) {
cell = [tableView dequeueReusableCellWithIdentifier:#"ModelCell"];
if (cell == nil) {
// only create a new cell if a dequeue was not successful.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"ModelCell"] autorelease];
}
// whatever happened before you have a valid cell here.
// configure cell:
NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category == %#", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:#"#distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];
cell.textLabel.text = model;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"model == %#", model]] count]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if you want to optimize your code you could move the options that are the same for every cell inside the (cell == nil) condition. For example setting the selectionStyle, or changing the textcolor
Alex - if I look at your code right at the top, you're doing this:
cell = [tableView dequeueReusableCellWithIdentifier:#"ModelCell"];
However, all the examples (and my code) require a static NSString for the CellIdentifier
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
This then works the intended way.
You definitely reuse your cells . if you put your configuration inside if(cell == nil) , it works when no cell is reused . so please put the following code snippet outside of if(cell == nil) condition------------
if(cell == nil)
{``
// enter code here
}
NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category == %#", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:#"#distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];
cell.textLabel.text = model;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"model == %#", model]] count]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

UITableview dequeueReusableCellWithIdentifier false result

I'd done following code, on which I get repeat result from 10 index. (indexPath.row)
my data is in Dictionary
What could be the reason?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger index = indexPath.row;
NSLog(#"Current cell index : %d",index);
static NSString *CellIdentifier = #"CellIndetifier";
BOOL isCellSelected = NO;
//ListViewCell *cell = (ListViewCell *)[table dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier] autorelease];
NSString * text = nil;
if(isMultipleSelect){
text = [dicData objectForKey:[sortedData objectAtIndex:index]];
if([sIndexes containsObject:[sortedData objectAtIndex:index]]){
isCellSelected = YES;
}
}
cell.textLabel.text = text;
}
return cell;
}
You get wrong result because you setup cell's text only when it is created, while the same cell can be used for several different rows. You need to move text-setting code outside of the creating cell block:
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier] autorelease];
}
NSString * text = nil;
if(isMultipleSelect){
text = [dicData objectForKey:[sortedData objectAtIndex:index]];
if([sIndexes containsObject:[sortedData objectAtIndex:index]]){
isCellSelected = YES;
}
}
cell.textLabel.text = text;
You need to refactor the code like this:
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier] autorelease];
}
NSString * text = nil;
if(isMultipleSelect){
text = [dicData objectForKey:[sortedData objectAtIndex:index]];
if([sIndexes containsObject:[sortedData objectAtIndex:index]]){
isCellSelected = YES;
}
}
cell.textLabel.text = text;
The if (cell == nil) path is to allocate a new cell if dequeueReusableCellWithIdentifier: didn't return anything. The rest of the code needs to be same for both cases: set up the cell.

UITableview Section Error - objc_msgSend

If I make a section the error occurs.
I've already tried to set the section index to 0 and 1 but that didn't help either.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifier1 = #"Cell1";
if(indexPath.section == 1) {
if(indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.text = #"test 1";
}
return cell;
}
else if(indexPath.row == 1) {
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
cell1.text = #"test 2";
}
return cell1;
}
}
else if(indexPath.section == 2) {
if(indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.text = #"test 1";
}
return cell;
}
else if(indexPath.row == 1) {
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
cell1.text = #"test 2";
}
return cell1;
}
}
}
Sections and rows start at 0. As far as I can see, you don't return a cell for indexPath with section 0, row 0.
Edit: re-posting the source code (more readable):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifier1 = #"Cell1";
if(indexPath.section == 1) {
if(indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.text = #"test 1";
}
return cell;
}
else if(indexPath.row == 1) {
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
cell1.text = #"test 2";
}
return cell1;
}
}
else if(indexPath.section == 2) {
if(indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.text = #"test 1";
}
return cell;
}
else if(indexPath.row == 1) {
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
cell1.text = #"test 2";
}
return cell1;
}
}
}
Basic question. Have u updated the number of sections in - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section.
Normal obj msg send error.. comes when you are acessing something you have released or something which you do not own..
for example...
in the init method of the table view you write this code
sectionArray =[NSArray arraywithcontentsoffile:xyz.plist]
and in the numberofRowsInSection you use something like this
[sectionarray count];
wherein sectionArray is an instance variable..
Thanks for your replies!
I've wrote the whole code once more and run it every time i added a line of code. That helped.
I think the problem was the if(indexPath.section == 0) and so on.
I only set the content for 2 of the 3 sections.
But i'm not sure wheather this was the problem.
Thanks for your great help!
As a beginner objective c is not that easy :)

objective-C syntax beginner question

i want to use the appRecord.myName in the viewDidLoad,
when i put it there it error up that appRecord is undeclared, how to declare it?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"pilotWay";
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell";
int nodeCount = [self.entries count];
if (nodeCount == 0 && indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:PlaceholderCellIdentifier] autorelease];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.detailTextLabel.text = #"load";
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (nodeCount > 0)
{
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = appRecord.myName;
cell.textLabel.text = appRecord.appName;
}
return cell;
}
Do you have #import "AppRecord.h" at the top of that file?
It appears that appRecord is declared (= does that). Perhaps you need to cast it, though: (AppRecord *)[self.entries objectAtIndex:indexPath.row]. Whatever you do, to check whether appRecord exists, try the following and run:
NSLog(#"appRecord: %#", appRecord);
You should get a description of the object appRecord with a memory address if it exists. Let me know if any of this helps, or if you need further explanation.