I created UITableView inside my UIViewController and I built a prototype cell in the storyboard. I assigned tags for all the elements in the cell I want to change and I am changing them in the code.
When the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is called, my data is processed and I can see a cell appear with the red background colour I set in storyboard, however the images or text is missing. I think the problem is with the implementation but I can't figure out what I am doing wrong.
This is what the storyboard looks like:
This is the relevant code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
if(tableView == youLikeTableView)
{
UIView* youLikeImageFrame = (UIView *)[cell.contentView viewWithTag:100];
UIImageView* youLikeImageView = (UIImageView *)[cell.contentView viewWithTag:101];
UILabel *youLikeNameLabel = (UILabel *)[cell.contentView viewWithTag:102];
for(int i = 0; i < [youLike count]; i++)
{
youLikeImageFrame.layer.cornerRadius = youLikeImageFrame.frame.size.width / 2;
[youLikeImageView setImage:[youLikeImages objectAtIndex:i]];
youLikeImageView.layer.cornerRadius = youLikeImageView.frame.size.width / 2;
youLikeNameLabel.text = [youLikeName objectAtIndex:i];
}
}
return cell;
}
And this is the cell appearing without the text or images
you forgot to add them as subview
[cell addSubView:youLikeImageFrame];
[cell addSubView: youLikeImageView]; and
[cell addSubView: youLikeNameLabel];
just before
return cell;
Related
UITableView's cellForRowAtIndexPath look like this :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell Identifier";
cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if(cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
UILabel *likelabelnew = [[UILabel alloc]init];
likelabelnew.frame = CGRectMake(230,5,50,20);
likelabelnew.text = #"old text";
likelabelnew.tag=indexPath.row;
[cell addSubview:likelabelnew];
}
return cell;
}
Add this code whereever you want to update your cell text. Suppose you have to update UILabel with tag 100 . Then add one more check :
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSArray *subviews = cell.subviews;
for (UIView *subview in subviews) {
if ([subview isKindOfClass:[UILabel class]] && subview.tag == 100) {
UILabel *mylabel = (UILabel *)subview;
//Update your lable here
}
}
Try this.
First of all you don't need to add custom UILabel in the function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Then do this where you want to update your label.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *label = cell.textLabel;
label.frame = CGRectMake(10,10,230,31);
label.text = #"Your text";
I am having some odd behaviour with my UITableView. When I scroll up and down sometimes the bottom row will vanish and disappear again. Not sure why this is happening. Each of my UITableCells contains 4 buttons like so :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
int x,y;
x=5;
y=0;
for(int i = (int)indexPath.row*4; i<(int)indexPath.row*4+4; i++) {
//make sure we don't hit a blank in the array
if(i<[self.buttons count]) {
UIButton *button = [[UIButton alloc] init];
button = self.buttons[i];
button.layer.cornerRadius = button.frame.size.width / 2;
button.clipsToBounds = YES;
[button setFrame:CGRectMake(x, y, 70, 70)];
[cell.contentView addSubview:button];
x+=80;
}
}
return cell;
}
Could this be because I have the same cell reuse identifier for each cell? Does it need to be unique?
In this code:
UIButton *button = [[UIButton alloc] init];
button = self.buttons[i];
You allocate and initialize a button and then reassign the variable to entry i of a buttons array. Was this meant to be something else?
Also you are adding buttons to the cell content as a subview. Cells are reused when you scroll, so you could easily be adding more than 4 buttons to a given cell which will be causing you display issues. When you dequeue a cell it could already have 4 buttons in it.
Can you not just have 4 buttons in the cell prototype, saving you all this effort in the code.
No, cell reuse identifier need to be constant for a tableView. However you should use is as a static variable.
Change to static NSString *cellID = [NSString stringWithFormat:#"cellID",indexPath.row]; instead of
NSString *cellID = [NSString stringWithFormat:#"cell%d",indexPath.row];
Also are you making any changes in willDisplayCell or didEndDisplayingCell delegate methods. If yes Plz post that code too.
Re-write like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if (cell.contentView.subviews.count == 0) {
int x,y;
x=5;
y=0;
for (int i = 0; i < 4; i++) {
UIButton *button = [[UIButton alloc] init];
button = self.buttons[i];
button.layer.cornerRadius = button.frame.size.width / 2;
button.clipsToBounds = YES;
[button setFrame:CGRectMake(x, y, 70, 70)];
[cell.contentView addSubview:button];
x+=80;
}
}
return cell;
}
- (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];
return cell;
}
}
I've got an UITableView with 30 objects.
Controller shows correctly first 13 rows, on 14th row use a "joker" row which changes his content scrolling, then start again with first thirteen row and "joker" row until the end.
That's code of cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: #"cell" forIndexPath:indexPath];
UIImageView * flagImageView = (UIImageView *) [self.view viewWithTag:1];
UILabel * nationLabel = (UILabel *) [self.view viewWithTag:2];
nationLabel.text = [_nationsArray objectAtIndex:indexPath.row];
nationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
NSLog(#"%i", indexPath.row);
return cell;
}
Strange thing is that configuring cell in if (cell == nil) { ... } it doesn't work...
The problem seems to be with the nationLabel. When I replaced
UILabel * nationLabel = (UILabel *) [self.view viewWithTag:2];
nationLabel.text = [_nationsArray objectAtIndex:indexPath.row];
with
cell.textLabel.text = [_nationsArray objectAtIndex:indexPath.row];
it's working fine (at least the text). So I think you should try to make a UITableViewCell subclass, make property for that label and see if it's ok then.
Don't use this
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: #"cell" forIndexPath:indexPath];
Change your code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: #"cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
UIImageView * flagImageView = (UIImageView *) [self.view viewWithTag:1];
UILabel * nationLabel = (UILabel *) [self.view viewWithTag:2];
nationLabel.text = [_nationsArray objectAtIndex:indexPath.row];
nationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
NSLog(#"%i", indexPath.row);
return cell;
}
I would to create a custom cell without create a custom cell class. I know that this is possible. I've created in storyboard a tableviewcontroller with a prototype cell with a label. In the attibutes I've set the cell name "mycell". And the code that I used is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *CellIdentifier = #"mycell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];}
UILabel *title = (UILabel*) [cell viewWithTag:1];
title.text = #"Hi";
return cell;
}
But when my app run I see only a empty table without a cell with my label.
In the tableView methods I've used:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5; }
Thank you.
If you are adding UILabel programmatically it needs to be alloc init, should be given a frame and added to the cell as sub view.
UILabel *title = (UILabel*) [cell viewWithTag:1];
title.text = #"Hi";
return cell;
Should be
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(50, 10, 50, 20)];
title.text = #"Hi";
[cell addSubview:title];
return cell;
I've subclassed the UITableViewCell to add custom appearance to it. At the init level of the MYTableViewCell I added 4 subviews: UIImageView, and three UILabel(s). All 4 subviews have a different Tag assigned to them.
Inside the cellForRowAtIndexPath method I either create a new cell if it wasn't available at first, or reuse available one and assign the proper text to the ui labels.
The problem I am having is that if I try to scroll super fast, then the data gets messed up, however if I scroll up and down more slowly, then everything works fine.
Any thoughts??
Below is the code:
- (MyTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"itemListTableViewCell";
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
DisplayableEntity *displayableEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];
if( ! cell ) {
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[self tableView:tableView appearanceForCell:cell withEntity:displayableEntity];
} else {
UIImageView *imageView = (UIImageView *) [cell viewWithTag:IMAGEVIEW_TAG];
imageView.image = [UIImage imageNamed:displayableEntity.displayImageName];
UILabel *titleLabel = (UILabel *) [cell viewWithTag:TITLEVIEW_TAG];
titleLabel.text = displayableEntity.entityName;
UILabel *itemDescription = (UILabel *) [cell viewWithTag:DESCRIPTION_TAG];
itemDescription.text = displayableEntity.entityDesctiption;
}
}
// some code removed to make it brief
- (void)tableView:(UITableView *)tableView appearanceForCell:(MyTableViewCell *)cell withEntity:(DisplayableEntity *)entity {
// cell image view
UIImageView *cellImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[entity displayImageName]]];
[cellImageView setTag:IMAGEVIEW_TAG];
[cell addSubview:cellImageView];
// adding entity name label
UILabel *itemTitleName = [self itemTitleNameLabelWithFrame:itemNameLabelRect itemName:[entity entityName]];
[itemTitleName setTag:TITLEVIEW_TAG];
[cell addSubview:itemTitleName];
// adding 'assigned to' label right under the item name label
UILabel *itemDescriptionLabel = [self itemDescriptionLabelWithFrame:descriptionLabelFrame itemDescription:[entity entityDesctiption]];
[itemDescriptionLabel setTag:DESCRIPTION_TAG];
[cell addSubview:itemDescriptionLabel];
}
I see some troubles in tableView:cellForRowAtIndexPath: logic
It should be:
Dequeue cell
If cell cannot be dequeued - create the new one
Set all cell properties
I mean something like this:
- (MyTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"itemListTableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} // <-- Note there is no else, we should reset properties in both cases
NSManagedObject *managedObject = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [managedObject valueForKey:#"text"];
cell.imageView.image = [managedObject valueForKey:#"image"];
return cell;
}