UILabel subview in UITableViewCell isn't showing up. (iPhone Dev) - iphone

I have a cell in a table view that has a UILabel as a subview, when I set the text of the label, it is never shown on the cell. I'm somewhat a noob in iPhone development and am not sure what I'm doing wrong...
I am creating and returning the following cell in my table view's cellForRowAtIndexPath delegate:
cell = [[[ActivityCell alloc] initWithFrame:
CGRectZero reuseIdentifier:ColumnedCell] autorelease];
CGRect frame = CGRectMake(180.0, 11.0, 130.0, 22);
UILabel *valueField = [[UILabel alloc] initWithFrame:frame];
[valueField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
valueField.tag = 111;
valueField.textAlignment = UITextAlignmentRight;
valueField.textColor = [UIColor colorFromHex:#"326799"];
valueField.highlightedTextColor = [UIColor whiteColor];
valueField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
valueField.adjustsFontSizeToFitWidth = YES;
[cell.contentView addSubview:valueField];
[valueField release];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
I then want to set the UILabel (subview) later by doing this (I currently have this code in viewDidAppear):
ActivityCell *cell = (ActivityCell*)[formDetailsTableView cellForRowAtIndexPath:
[NSIndexPath indexPathForRow:0 inSection:1]];
UITextField *valueField = (UITextField *)[cell viewWithTag:111];
valueField.text = #"foo";
But the word "foo" never shows up in the UILabel. I believe it shows up when I compile with <= 2.2 SDK, but I want to get this working with 3.0+
Any ideas of why the text isn't showing up?
FOLLOW UP:
Please take a look at this question as a follow up to this: UITableViewCell's textLabel is overlapping a subview label, how can I fix it? (iPhone Dev)

Well first off, you're creating a UILabel, tagging it as 111, and then adding it as a subview to the cell's contentView. Later on, you are trying to retrieve that UILabel but you're casting it to a UITextField. Fundamentally something you're doing here is wrong.
Here's what I recommend doing:
Take a look at Apple's guide for using Interface Builder to create cells. It's going to lead to a lot less code and you'll be able to easily see what's going on, and won't have to add the Label/TextField programatically.
Instead of trying to access cells directly in viewDidAppear and changing their subviews, you should be doing all of that display logic inside of cellForRowAtIndexPath. In another method (for example, one called when the user touches a button), you'll modify some data structure and then send the tableView the reloadData message. At that time, cellForRowAtIndexPath is called again and the values set in your data structure determines how the cell is created.

It looks like you have a small bug:
change
UITextField *valueField = (UITextField *)[cell viewWithTag:111];
to
UITextField *valueField = (UITextField *)[cell.contentView viewWithTag:111];

My guess is that the cell coming back is nil and thus not updating your text. I would start buy making sure you are getting a cell back from this line:
ActivityCell *cell = (ActivityCell*)[formDetailsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];

cell = [[[ActivityCell alloc] initWithFrame:
CGRectZero reuseIdentifier:ColumnedCell] autorelease];
your cell has a frame of CGRectZero

Related

Get subview (UITextField or UILabel) of UITableViewCell -- two ways, one works, one doesn't - why?

I have a UITableViewCell designed via a Storyboard that contains a UITextField and UILabel. I want to update the values of these views when cellForRowAtIndexPath is called.
I first tried to get references to the textfield and label like this:
UITextField *textfield = (UITextField*)[cell.contentView viewWithTag:10];
UILabel *label = (UILabel*)[cell.contentView viewWithTag:20];
This worked for the UILabel, but I was only able to get the reference to UITextField the first time the cell was created, I was able to set the original value (textField.text) but never update it. If I inspect the array of subviews I can see that the UITextField is there, I just can't get to it with viewWithTag. I switched to this (below) and it works:
UITextField* textField = [[cell.contentView subviews] objectAtIndex:0];
UILabel *label = [[cell.contentView subviews] objectAtIndex:1];
Why doesn't the first approach work? What's the right way to do this?
This code is in the context of:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DetailCell" forIndexPath:indexPath];
UITextField* textField = [[cell.contentView subviews] objectAtIndex:0];
textField.text = #"<something>";
UILabel *label = [[cell.contentView subviews] objectAtIndex:1];
label.text = #"<something else>";
return cell;
}
Sorry. This was just a bug at my end, I apologize for wasting your time. I was overriding the value for textField.tag that had been set in the Storyboard UI. (I relied on it being the value set in Storyboard which was not the case). The original code runs correctly. Still not sure which approach is better. Is it safer to assume a specific index or a specific tag value? Neither of these seems safe to me.

UITableView Cell Label Duplicating

I have a UINavigationController full of UITableViews and I use custom cells in a specific one of these.
In tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath I add a UILabel with [cell addSubview:label];
This works great, however if I then go into the detail view, then return back, it duplicates the label. How can I stop this?
Thanks.
The problem is that you are adding a new label every time the cell gets reused and displayed again.
Since you're using a custom cell already, the easiest solution would be to give the cell a UILabel property, and use that instead of adding a new label each time. Specifically, you should only add a new label if you're creating a cell instead of getting a recycled one. Or, you could add a new UILabel only if the property is nil.
Or as an alternative to adding the label in the custom class, just make sure to add the label inside the conditional cell creation. e.g.
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ident];
if(cell == nil){
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease];
[cell.contentView addSubview:[[[UILabel alloc] init] autorelease]]; // <-------
}
Add a tag to the label, then check if it exists
UILabel *label;
if ([cell viewWithTag:2]){
label = [cell viewWithTag:2];}
else{
label = [[UILabel alloc]init];label.tag = 2;}

UITableViewCell from contentView subview

I have created the cells with labels and using checkaMarksAccessory. The few last cells have UITextFields which can user modifi, and those have selector on UIControlEventEditingDidEnd where i want change the state of the cell to checked.
How can i get the cell in the selector? Doesn't have the object some parentView?
The way i inserting the object to cell.
UITextField *textfield = [[UITextField alloc] initWithFrame:CGRectMake(10, 25, 200, 30)];
[textfield setBorderStyle:UITextBorderStyleRoundedRect];
[textfield addTarget:self action:#selector(vybavaDidFinishEdit:) forControlEvents:UIControlEventEditingDidEnd];
[cell.contentView addSubview:textfield];
I'm not sure if it's safe to assume cell.contentView.superview == cell. Might Apple change this? I doubt it. But, I don't see anywhere in the documentation that says a cell's content view is a direct subview of the cell.
If you've added a UIGestureRecognizer to one of your subviews of the cell's content view, then you can get a reference to the cell with:
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[gestureRecognizer locationInView:self.tableView]];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
Table View Animations and Gestures sample code uses indexPathForRowAtPoint: this way.
If you must traverse superviews, I think using a function like the one below is a bit safer.
UITableViewCell *ACMContentViewGetCell(UIView *view)
{
while ((view = view.superview)) {
if ([view isKindOfClass:[UITableViewCell class]]) {
return (UITableViewCell *)view;
}
}
return nil;
}
But that function still assumes contentView is within its cell, which I also didn't see anywhere in the documentation.
So perhaps, the best solution is to rearchitect your code so that you don't need to get cell from contentView, or if you must, then add an instance variable from the subview of contentView to cell.
ok so the way is to use superview. The superview is component which own the object. If i want get the UITableViewCell from UITextField i used [[UITextField superview] superview].

iPhone SDK - Highlight the selected cell in TableView

I have a customTableViewCell in a tableView. I am highlighting the cell when selected using,
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
But, the tableView appears like the following image.
It hides the labels and text in the customCell. I just want to highlight the cell simply without hiding the background image and labels. I do not know where I am making the mistake, whether in code or IB. .
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.Your_imageView.highlightedImage = [UIImage imageNamed:#"Your_image_Name.png"];
this will work fine
Hey i think you need to add labels and texts in the customCell to cell.contentview. For reference go to Apple developer document.
http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7
[_tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
put this in to view Will Appear and its works for me ,
NSIndexPath *selectedIndexPath;
also put this to .h file too
Try this
UIView *viewSelected = [[[UIView alloc] init] autorelease];
viewSelected.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:#"cell_highlighted.PNG"]];
cell.selectedBackgroundView = viewSelected;

Editable tableHeaderView in UITableView (like Contacts App)

I'm currently trying to implement a editable details view using a grouped UITableView. I'd like it to look like the Contacts application:
in viewing-state it should display the header as plain label (in Contacts it's the name with TRANSPARENT background).
in editing-state it should display the header as editable UITableViewCell (in Contact's the tableHeader? changes from just the plain text with transparent background to a standard UITableViewCell with white background).
I'm not really sure what the best way is the achieve this. First I've tried to add the header as UILabel tableHeaderView (which works great), but then I cannot switch this to a UITableViewCell. A possibility would be to remove the header and add a new section when entering editing mode.
Currently I'm trying to always use a UITableViewCell and make it transparent in viewing mode and switch it to default in editing mode. However, I haven't been able to make the UILabel of the UITableViewCell (which is in UITableViewCellStyleDefault) transparent (although I did manage to make the UITableViewCell transparent, but not the textLabel inside it).
What is the best way to implement this behavior?
I've done this too (although a moot point with the changes to the Contacts app in iOS4!) My solution uses two different header views and switches between them based on isEditing:
- (UIView *)infoHeaderAnimated:(BOOL)animated {
UIView *header = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 90.0)] autorelease];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(98.0, 41.0, 221.0, 21.0)];
label.font = [UIFont boldSystemFontOfSize:17.0];
label.backgroundColor = [UIColor clearColor];
label.text = baseEntity.labelText;
[header addSubview:label];
[label release];
return header;
}
- (UIView *)editingHeaderAnimated:(BOOL)animated {
UIView *header = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 90.0)] autorelease];
UITableView *tv = [[UITableView alloc] initWithFrame:CGRectMake(78.0, 10.0, 240.0, 90.0) style:UITableViewStyleGrouped];
tv.backgroundColor = [UIColor clearColor];
tv.dataSource = self;
tv.delegate = self;
tv.rowHeight = 62.0; //### height of cell and frame depend on elements
tv.tag = kEditingHeaderTag;
editingHeaderTableView = [tv retain];
[header addSubview:tv];
[tv release];
return header;
}
What you are trying to do is very standard, consider implementing these protocols in the UITableViewDatasource, especially the titleForHeaderInSection & commitEditingStyle:
Configuring a Table View
– tableView:cellForRowAtIndexPath: required method
– numberOfSectionsInTableView:
– tableView:numberOfRowsInSection: required method
– sectionIndexTitlesForTableView:
– tableView:sectionForSectionIndexTitle:atIndex:
– tableView:titleForHeaderInSection:
– tableView:titleForFooterInSection:
Inserting or Deleting Table Rows
– tableView:commitEditingStyle:forRowAtIndexPath:
– tableView:canEditRowAtIndexPath:
Remember to choose the type of your TableView as Group instead of Plain in the Interface Builder.