Custom UITableViewCell Doesn't Draw Corectly - objective-c

I'm having a really weird issue with my custom UITableViewCell. I have a cell with an identifier of "ThreadCell" in Interface Builder with some custom labels. These labels are tagged so I can access them.
In my code, I am doing the following:
static NSString *CellIdentifier = #"ThreadCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: #"ThreadCell"];
}
Person *person = [self.people objectAtIndex: indexPath.row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag: 0];
nameLabel.text = person.nickname;
return cell;
This seems to work fine, with one exception. The TableView draws like this:
This obviously isn't my custom cell. But the weird thing is, when I tap on a cell, I get this:
This is my custom cell, drawn behind the default cell. What?! I'm not sure how this is happening because I do not ever set the title of the textview anywhere, so I'm not sure where the first John Smith comes from.
Anyone have any ideas?

In your code, you allocate a plain UITableViewCell and not an instance of your custom cell. Setting a reuseIdentifier in initWithStyle is not sufficient to load an instance of a custom cell class.
If you develop for iOS 5 and later, then you can use registerNib:forCellReuseIdentifier: to register a NIB file containing your custom cell. dequeueReusableCellWithIdentifier: will then always return an instance of that NIB.

Related

UITableView random crash with cell.contentview set

i am working on a uitableview and i am getting random crashes with when i use custom uiviewcontroller inside a uitableviewcell.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
SuspectSalesResponse* r = [valueArray objectAtIndex:indexPath.row];
SuspectSalesCellViewController* scellView = [[SuspectSalesCellViewController alloc]initWithNibName:#"SuspectSalesCellViewController" bundle:nil cellData:r];
if(![cellViewArray containsObject:scellView])
[cellViewArray addObject:scellView];
[cell.contentView addSubview:scellView.view];
}
return cell;
This code sometimes work, sometimes it gives the folowing error:
* -[SuspectSalesHeaderViewController _parentModalViewController]: message sent to deallocated instance 0x8556880
i've tried keeping contentviews within an array (cellViewArray) but no luck i am still getting this error. What am i doing wrong?
Thanks for helping!
The problem is that you are not supposed to add view controllers inside table cells. You should try to change from UIViewController to UIView.
The exact reason for your crash is that you create a controller (which has a view) and you are adding the view to your cell, but the controller object is lost. When the view sends whatever notification to it's parent controller, the controller is already deallocated and there is where you get your bad access. This will be solved if you transform your SuspectSales~ to a UIView subclass
EDIT
To load a UIView (or any subclass) from a nib file, you must first create the xib, set the view's class to your class (you do it in the third tab on the interface builder).
After that, you can load it with this code:
Generic function in some utility class
+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass {
if (nibName && objClass) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil];
for (id currentObject in objects ){
if ([currentObject isKindOfClass:objClass])
return currentObject;
}
}
return nil;
}
In your class:
Subclass *view = [UtilityClass loadNibNamed:#"Subclass" ofClass:[Subclass class]];

Labels in Custom Cell do not appear

I am new to iphone development. I am using xCode 4.2 with storyboard. I am trying to get cells in my tableview to display several uilabels. They just aren't appearing in my simulator. but the original cell.textLabel is appearing.
here's what I did:
I created a new customcell.h/.m files that extend the UITableViewCell. I added some instance variables in the class. I went to the storyboard and in the class of the identity inspector of the tableviewcell, i changed it to point to customcell. I dragged and dropped some UIlabels into my new cell. I then went to the connection inspector to drag those "plus" icons with lines to connect to my new uilabels to my instance variables.
When I run my simulator, I don't see any of my new ui labels. I only see the original uilabel of cell.textLabel. I can programmatically get and set cell.mylabel1, cell.mylabel2 etc..., which are new labels, but hey just are not appearing.
Additioanl Details
This i the cellForRowAtIndexpath function for my tableviewcontroller.
static NSString *CellIdentifier = #"Cell"; // this was the error, i needed to change this to CustomCell, or whatever it is in my storyboard
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.mylabel1.text = #"hello"; // doesn't appear in simulator
cell.textLabel.text = #"world"; // does apepar in the simulator
As David has alluded, the one missing piece here is that you need to reference the Identifier of the cell specified in the Storyboard:
First, specify an identifier in the "Attributes Inspector" in the storyboard. You can do this by selecting the UITableViewCell and adding an identifier "ExampleCell" (for example). Second, reference this identifier in the code when creating the CustomCell.
static NSString *CellIdentifier = #"ExampleCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

xcode / cocoa: Reuse identifiers in custom cells

I have a tableview with custom cells via a uitableviewcell subclass. The cells have a label lblResult that changes after a a result is received. It works well, but, when I then scroll down my tableview, other random cells now have that same result label (but they still have their proper "name" label).
I figure this has to do with reuse identifiers, but I'm not sure.
Let me know if you need any more code to understand my problem.
The cell is made like this in cellForRowAtIndexPath
static NSString *CellIdentifier = #"tableCell";
FriendCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[FriendCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil];
}
Then before being returned, cell is passed into a loadingQueue dictionary.
When the result loads there is a resultComplete method which loads the cell from the loadingQueue dictionary and the following is called:
[[cell lblNumTagged] setText:[NSString stringWithFormat:#"(%d)",[thisDictionary count]]];
[[cell lblNumTagged] setHidden:NO];
Yes it is because cells are being re-used.
In your custom cell class you can use the prepareForReuse delegate method, which is being called before the cell is being reused and clear the cell's label there...
I know this is old but just in case. I think it is because when you create a new cell you are NOT specifying the identifier.
static NSString *CellIdentifier = #"tableCell";
FriendCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[FriendCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
Try it like this, note the end of the last line.....

Confusing syntax with custom UITableViewCell

I have found this code for a custom UITableViewCell :
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:nil options:nil];
MyCustomCell *customCell = [[MyCustomCell alloc]init];
MyCustomCell.cellImage = [arrayImages objectAtIndex:indexPath.row];
for (UIView *view in views)
{
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (MyCustomCell *)view;
}
}
}
and I could not figure how this specific part works: cell = (MyCustomCell *)view;
I wanted to change it for my previously created instance of MyCustomCell (customCell)... How could I do that?
Sometimes people will create a custom UITableViewCell using Interface Builder. This person is just loading their custom UITableViewCell subclass and assigning it to the cell. The line: cell = (MyCustomCell *)view; presumable works because MyCustomCell is a subclass of UITableViewCell.
This is just another technique for creating custom cells sometimes you'll see a similar thing done with tags.
First, it's iterating over a collection of UIViews, or UIView subclasses. It's storing each iteration's variable into a pointer called view.
It's then simply casting the current view variable to a type of MyCustomCell. Presumably MyCustomCell extends UIView, so this is legal.
This is useful if you want to use methods specific to MyCustomCell, as Xcode won't know they exist, if you don't explicitly Type Cast your object.

UITableViewCell losses repeated content in other cell

I've a UITableView which when a cell has the same content that other, this content only appear in the las cell drawed. My custom cell adds an UIView property to add dynamic subviews from other class.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"cell";
CollectionCell *cell = (CollectionCell *)[tableView
dequeueReusableCellWithIdentifier:MyIdentifier];
if (!cell) {
cell = [[[CollectionCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MyIdentifier]
autorelease];
}
[cell setCollectionView:/* Generated view in other class */];
return cell;
}
The concrete problem is:
My dynamic view is composed by, for example, 2 UILabels:
if label 1 is a title, the title is unique for each row -> No problem, renders fine.
if label 2 is a category, indexes from 0 to 5 have same category -> Only row at index 5 shows category label.
I can't create this labels in cell instantiation and add as subview because the cell content is all dynamic.
Thanks for your time and help.
UPDATE:
I can't create this labels in cell instantiation and add as subview because the cell content is all dynamic.
I'm going to explain it in detail:
The content and UI controls added to collectionView property can be differentes each execution. In one execution collectionView could have an UIImageView and a UILabel, and next execution it has 2 UILabels (for example). This is why I can't create something like this
if (!cell) {
cell = [[[CollectionCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MyIdentifier]
autorelease];
UILabel *foo = [[UILabel alloc] initWithFrame:SomeFrame];
[foo setTag:101];
[cell.collectionView addSubview:foo];
}
UILabel *foo = [cell.collectionView subviewWithTag:101];
[foo setTitle:#"This content is dynamic"];
Thanks!
Update 2:
Appears to be a problem with custom UILabel subclass. If I use original UILabel to show strings works fine.
You are not supposed to add subviews outside the block-
if (!cell) {
cell = [[[CollectionCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MyIdentifier]
autorelease];
}
your subviews should only be added inside this block (the first time the reusable cell is created).
everything that happens outside (after) this 'if' block happens multiple times as you scroll your table up and down so that's where you edit the added subviews (only after the whole 'if block, outside it).
See my answer here