I'm a newbie iOS developer writing my apps in Objective-C language. I found myself facing a problem, and I searched a lot, but without results :(
The problem is: I'm programmatically populating uitable view cells with an image, an "eyelet" and a title, parsed from a news xml grabbed online.
The code I'm going to past here under make the UI snaps, but I already found the cause and I'm working on the solution, so no problem about this, the fact is that this code load the contents, but when I try to open a second view controller with a news detail I previously made...well...the cells aren't clickable!
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UILabel *eyeletLabel, *newsTitleLabel, *dateLabel;
eyeletLabel = [UILabel new];
newsTitleLabel = [UILabel new];
newsImage = [UIImageView new];
if (cell == nil) {
//NSLog(#"Cell: %#", cell);
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
ATNews *thisNews = gNewsArray[indexPath.row];
eyeletLabel.numberOfLines = 0;
eyeletLabel.lineBreakMode = NSLineBreakByWordWrapping;
eyeletLabel.frame = CGRectMake(90.0f, 5.0f, cell.contentView.frame.size.width - 20, 20);
eyeletLabel.text = thisNews.eyelet;
eyeletLabel.textColor = [UIColor orangeColor];
newsTitleLabel.numberOfLines = 0;
newsTitleLabel.lineBreakMode = NSLineBreakByWordWrapping;
newsTitleLabel.frame = CGRectMake(90.0f, 20.0f, cell.contentView.frame.size.width - 50, 50);
newsTitleLabel.text = thisNews.title;
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSString *newDate = [formatter stringFromDate:thisNews.pubDate];
dateLabel.text = [NSString stringWithString:newDate];
for (id obj in thisNews.newsPhotos) {
NSUInteger counter = 0;
if ([obj isEqualToString: #"true"]) {
counter = counter + 2;
imageUrlFromArray = [thisNews.newsPhotos objectAtIndex:counter];
NSURL *imageURL = [NSURL URLWithString:imageUrlFromArray];
imageData = [NSData dataWithContentsOfURL:imageURL];
}
counter = counter + 3;
}
newsImage.frame = CGRectMake(5.0f, 5.0f, 70.0f, 70.0f);
if (thisNews.newsPhotos.count != 0) {
newsImage.image = nil;
newsImage.image = [UIImage imageWithData:imageData];
newsImage.contentMode = UIViewContentModeScaleAspectFill;
newsImage.layer.cornerRadius = newsImage.frame.size.width / 2;
[newsImage.layer setMasksToBounds:YES];
}
else {
newsImage.image = [UIImage imageNamed:#"no-image.png"];
newsImage.contentMode = UIViewContentModeScaleAspectFit;
newsImage.layer.cornerRadius = newsImage.frame.size.width / 2;
[newsImage.layer setMasksToBounds:YES];
}
[cell addSubview:newsImage];
[cell addSubview:eyeletLabel];
[cell addSubview:newsTitleLabel];
[cell addSubview:dateLabel];
}
else {
//NSLog(#"Cell");
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
}
return cell;
}
I searched for the solution a lot, I also read some similar question in here too, but without success, could you help me? Thank you very much!
Implement the delegate method
- (void)tableView:(nonnull UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath;
Now that it is clickable, you need to either add a segue from your cell to your new view controller or from your view controller create a segue to the new view controller and call
[self.viewcontroller performSegueWithIdentifier:#"Your Identifer"];
Related
The UITableView row cannot be loaded after row 13. The data reload from 0 again.
i found out that the row is loaded until 13. And the row will start again from beginning.
If I set the height of each row to 20. All the row can be loaded in one screen then everything fine.
but I need to set the height to 40. then it has the problem.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"GroupsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
NSLog(#"test indexpath = %ld",(long)indexPath.row);
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
if(indexPath.row == 0){
UIImageView *profileImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10.0, 10, 80.0, 80.0)];
NSString *url = [[NSString alloc] init];
NSString *tempurl =self.iconimgpath;
NSLog(#"tempurl = %#",tempurl);
url = [NSString stringWithFormat:#"%#",tempurl];
NSURL * imageURL = [NSURL URLWithString:url];
profileImageView.contentMode = UIViewContentModeScaleAspectFit;
[profileImageView sd_setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:#"loadinglogo.png"]];
profileImageView.tag = 11;
if([cell.contentView viewWithTag:11])
[[cell.contentView viewWithTag:11] removeFromSuperview];
[cell.contentView addSubview:profileImageView];
//[cell.contentView addSubview:profileImageView];
}
else{
if(_feedItems.count>0 && (indexPath.row > 0))
{
UILabel * groupnamelabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 15.0, 300,20)];
groupnamelabel.text = [_feedItems[indexPath.row-1] groupname];
//groupnamelabel.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:18];
groupnamelabel.tag = 99;
if([cell.contentView viewWithTag:99]){
[[cell.contentView viewWithTag:99] removeFromSuperview];
}
[groupnamelabel setFont:[UIFont systemFontOfSize:15]];
[cell.contentView addSubview:groupnamelabel];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(pushAction:)];
[groupnamelabel addGestureRecognizer:tap];
groupnamelabel.userInteractionEnabled = YES;
}
}
return cell;
I found out the problem is
self.MyGrouptableview = [[UITableView alloc] initWithFrame:CGRectMake(0,65,screenWidth,screenHeight-150) style:UITableViewStylePlain];
If I set the height of the tableview long enough everything would be alright but the user cannot scroll to the bottom.
Something weird going on here. I have a tableview, and in each row there is a segmentedcontrol. The meaning of this is, that there only has to be one segmented control selected at all time. On a click of a 'control item', there is a segue that is pushed.
If I constantly select items of different segmented controls, there is nothing going on, my code works perfectly. When i select an different item from the same segmented control, i have this error:
nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
Unbalanced calls to begin/end appearance transitions for .
This is my code:
#interface PerformancesController ()
{
GFilm* currentFilm;
GTimePerformance* chosenTimePerf;
}
#end
#implementation PerformancesController
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [currentFilm.dayList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCustomCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myCustomCell"];
}
CAGradientLayer *bgLayer = [BackgroundLayer blackGradient];
bgLayer.frame = cell.bounds;
[cell.contentView.layer addSublayer:bgLayer];
cell.contentView.backgroundColor = [UIColor darkGrayColor];
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if(indexPath.row == 0)
{
CGRect rctStreep = cell.bounds;
rctStreep.origin.y = rctStreep.origin.y+1;
rctStreep.size.height = 1;
UIImageView* imgv = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"streep.png"]];
imgv.backgroundColor = [UIColor blackColor];
imgv.frame = rctStreep;
[cell.contentView addSubview:imgv];
}
CGRect rctStreep = cell.bounds;
rctStreep.origin.y = rctStreep.origin.y + rctStreep.size.height;
rctStreep.size.height = 1;
UIImageView* imgv = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"streep.png"]];
imgv.backgroundColor = [UIColor blackColor];
imgv.frame = rctStreep;
[cell.contentView addSubview:imgv];
imgv = nil;
NSArray* dayList = currentFilm.dayList;
GDay* d = (GDay*)[dayList objectAtIndex:indexPath.row];
CGRect rctDayLabel = CGRectMake(15, 7, 80, 30);
UILabel* lblDay = [[UILabel alloc]initWithFrame:rctDayLabel];
lblDay.textColor = [GColor yellowAccentColor];
NSDate* date = d.date;
if([date isToday])
{
lblDay.text = #"Vandaag";
}
else if([date isTomorrow])
{
lblDay.text = #"Morgen";
}
else
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd/MM"];
lblDay.text = [formatter stringFromDate:date];
}
[cell.contentView addSubview:lblDay];
NSMutableArray* itemArray = [[NSMutableArray alloc]init];
int i = 0;
GTimePerformance* prevChosen = currentFilm.displayPerformance;
int gekozen = -1;
for(i; i < [d.timeIdList count]; i++)
{
GTimePerformance* per = [d.timeIdList objectAtIndex:i];
if([per.performanceId isEqualToString:prevChosen.performanceId])
{
gekozen = i;
}
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm"];
[itemArray addObject:[formatter stringFromDate:per.performanceTime]];
}
float itemWidth = (cell.frame.size.width - (2* rctDayLabel.origin.x))/4;
MySegmentedControl *segmentedControl = [[MySegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(rctDayLabel.origin.x, cell.frame.size.height - rctDayLabel.origin.y - 30, itemWidth*[d.timeIdList count] , 30);
segmentedControl.segmentedControlStyle = UISegmentedControlStylePlain;
segmentedControl.tintColor = [GColor filterComponentColor];
if(gekozen >= 0)
{
[segmentedControl setSelectedSegmentIndex:gekozen];
}
[segmentedControl addTarget:self
action:#selector(clickedPerformance:)
forControlEvents:UIControlEventValueChanged];
UIFont *font = [UIFont systemFontOfSize:10.0f];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font
forKey:NSFontAttributeName];
[segmentedControl setTitleTextAttributes:attributes
forState:UIControlStateNormal];
segmentedControl.tag = 200 + indexPath.row;
[cell.contentView addSubview:segmentedControl];
return cell;
}
-(void)clickedPerformance:(id)sender
{
UISegmentedControl *segment = (UISegmentedControl*)sender;
if(segment.selectedSegmentIndex != -1)
{
int tag = segment.tag;
int i = 0;
for(i; i < [currentFilm.dayList count]; i++)
{
int diffTag = i + 200;
if(diffTag != tag)
{
UISegmentedControl* sControl = (UISegmentedControl*)[self.view viewWithTag:diffTag];
[sControl setSelectedSegmentIndex:UISegmentedControlNoSegment];
}
}
NSLog(#"lalala");
GDay* day = (GDay*)[currentFilm.dayList objectAtIndex:tag-200];
chosenTimePerf = [day.timeIdList objectAtIndex:segment.selectedSegmentIndex];
NSLog(chosenTimePerf.performanceId);
[self performSelector:#selector(goSegue) withObject:nil afterDelay:0.35];
}
}
-(void)goSegue
{
[self performSegueWithIdentifier:#"pushPrices" sender:self];
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: #"pushPrices"]) {
PricesController* pc = (PricesController*)[segue destinationViewController];
[pc setMovie:currentFilm andPerformance:chosenTimePerf];
}
}
#end
Why do you delay the goSegue method? hitting the item multiple times before afterDelay has elapsed will cause trouble.
I would change:
[self performSelector:#selector(goSegue) withObject:nil afterDelay:0.35];
to:
[self goSegue];
When I search in table view, it gives correct array, I am using NSPredicate to filter array. Even while debugging I came to know, it goes to cellForRowAtIndexPath and label is having data and everything is proper but as result there is only plain white default table view is shown, not the table which should be, after searching.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
preferredCustomCell *mycell = (preferredCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIView *backgroundView = [[UIView alloc] initWithFrame:mycell.selectedBackgroundView.frame];
[backgroundView setBackgroundColor:[UIColor colorWithRed:189/255.f green:189/255.f blue:189/255.f alpha:0.25]];
[mycell setSelectedBackgroundView:backgroundView];
SearchbackView.hidden = YES;
// Configure the cell...
if (mycell == nil) {
mycell = [[preferredCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
MyData *dealerData = Nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
dealerData = [searchResults objectAtIndex:indexPath.row];
} else {
dealerData = [cellData objectAtIndex:indexPath.row];
}
dealerInfo = [NSString stringWithFormat:#"%#\n%#\n%#%#%#%#%#\n%#\n%#", dealerData.businessName, dealerData.address, dealerData.city,#", ", dealerData.state, #", ", dealerData.zip, dealerData.phone, dealerData.email]; // data.address;
mycell.dealerInfoLbl.text = dealerInfo;
mycell.dealerInfoLbl.numberOfLines = 0;
mycell.selectDealerBtn.tag = indexPath.row;
// Assign our own background image for the cell
UIImage *background = [UIImage imageNamed:#"selectedCell"];
UIImageView *cellBackgroundView = [[UIImageView alloc] initWithImage:background];
cellBackgroundView.image = background;
mycell.selectedBackgroundView = cellBackgroundView;
mycell.lblPreferred.hidden = YES;
if (mycell.selectDealerBtn.tag==btnTag) {
if (selectDealer==true) {
[mycell.selectDealerBtn setImage:[UIImage imageNamed:#"selectedDealer"] forState:UIControlStateNormal];
[mycell.selectDealerBtn setTitle:#"Select" forState:UIControlStateNormal];
mycell.selectDealerBtn.imageEdgeInsets = UIEdgeInsetsMake(6, 16, 26, 17);
mycell.selectDealerBtn.titleEdgeInsets = UIEdgeInsetsMake(32,-66, 0, 10);
mycell.lblPreferred.hidden = NO;
}
}
else{
[mycell.selectDealerBtn setImage:[UIImage imageNamed:#"N99-selectDealerBtn"] forState:UIControlStateNormal];
[mycell.selectDealerBtn setTitle:#" " forState:UIControlStateNormal];
mycell.lblPreferred.hidden = YES;
}
return mycell;
I have a UITable that reuses cells. Each cell has an image dependant on a condition. The correct images are always used however when cells are reused the old image is displayed behind the new one. I have tried to remove the uiimageview before adding a new subview however it has no effect.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
return cell;
}
Any help would be greatly appreciated?
The problem is each time cellForRowAtIndexPath: is called you create a new imageview.
I corrected your code as follows:
Here we create an imageView once for each new new cell and replace it's image every time cellForRowAtIndexPath: is called:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
UIImageView *achievImg = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
//New Cell ... Create Image view
achievImg = [[UIImageView alloc] init];
achievImg.tag = 10;
[cell.contentView addSubview:achievImg];
}
else{
//Old cell...get previously createdd imageview
achievImg = (UIImageView*)[cell.contentView viewWithTag:10];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
//You don't need this because it doesn't have a superview in the first place..it's new
//[achievImg removeFromSuperview];
return cell;
}
try like this,
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
}
return cell;
}
You are always adding the imageView to the contentView of the cell. If the cell is reused that will lead to multiple imageViews in cell.
You can give a tag to the imageView. Always check if there is a view will same tag in the contentView of cell. If not add the imageView.
UIImageView *achievImg = (UIImageView *)[cell.contentView viewWithTag:55];
if(!achievImg){
achievImg = [[UIImageView alloc] init];
achievImg.tag = 55;
[cell.contentView addSubView:achievImg];
}
This is a chat app, I'm using tableview to display the chatting data between user and others, however I'v got Rows are displayed multiple(duplicate). The code is below:
#define kMyTag 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *messageDic = [self.chatArray objectAtIndex:indexPath.row];
if ([[messageDic objectForKey:#"myself"]boolValue] == false) {
static NSString *CellIdentifier = #"MessageChatFriendCell";
MessageChatFriendCell *cell = (MessageChatFriendCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MessageChatFriendCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *chatInfo = [self.chatArray objectAtIndex:[indexPath row]];
UIView *chatView = [chatInfo objectForKey:#"view"];
chatView.tag = kMyTag;
[cell.contentView addSubview:chatView];
return cell;
} else {
static NSString *CellIdentifier = #"MessageChatSelfCell";
MessageChatSelfCell *cell = (MessageChatSelfCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MessageChatSelfCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *chatInfo = [self.chatArray objectAtIndex:[indexPath row]];
UIView *chatView = [chatInfo objectForKey:#"view"];
chatView.tag = kMyTag;
[cell.contentView addSubview:chatView];
return cell;
}
}
the print results for each row are:
2012-08-02 15:44:47.152 MessageChatSelfCell-><UIView: 0x222790; frame = (85 0; 230 114); tag = 1; layer = <CALayer: 0x222320>>
2012-08-02 15:44:47.166 MessageChatFriendCell-><UIView: 0x21d790; frame = (0 0; 210 132); tag = 1; layer = <CALayer: 0x21d5c0>>
2012-08-02 15:44:47.176 MessageChatFriendCell-><UIView: 0x21bde0; frame = (0 0; 177 60); tag = 1; layer = <CALayer: 0x21be10>>
2012-08-02 15:44:47.183 MessageChatSelfCell-><UIView: 0x216430; frame = (85 0; 230 168); tag = 1; layer = <CALayer: 0x215fc0>>
2012-08-02 15:44:59.232 MessageChatFriendCell-><UIView: 0x215150; frame = (0 0; 86 60); tag = 1; layer = <CALayer: 0x214eb0>>
2012-08-02 15:45:00.465 MessageChatSelfCell-><UIView: 0x213220; frame = (85 0; 230 78); tag = 1; layer = <CALayer: 0x213250>>
Please advise, thanks!
Updated 2012-08-08
#define WRITER_NAME_LABEL_TAG 4
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MessageChatSelfCellIdentifier = #"MessageChatSelfCell";
static NSString *MessageChatFriendCellIdentifier = #"MessageChatFriendCell";
UITableViewCell *cell = nil;
UIView *chatView = nil;
NSDictionary *messageDic = [self.chatArray objectAtIndex:indexPath.row];
NSString *text = [messageDic objectForKey:#"compiled"];
BOOL myMessage = [[messageDic objectForKey:#"myself"] boolValue];
if (myMessage) {
cell = [tableView dequeueReusableCellWithIdentifier:MessageChatSelfCellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MessageChatSelfCellIdentifier];
chatView = [self bubbleView:[NSString stringWithFormat:#"%#", text]
from:YES];
chatView.tag = WRITER_NAME_LABEL_TAG;
NSLog(#"MessageChatFriendCell->%#",chatView);
[cell addSubview:chatView];
}else {
chatView = (UIView *)[cell viewWithTag:WRITER_NAME_LABEL_TAG];
}
} else {
cell = [tableView dequeueReusableCellWithIdentifier:MessageChatFriendCellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MessageChatFriendCellIdentifier];
NSString *text = [messageDic objectForKey:#"compiled"];
UIView *chatView = [self bubbleView:[NSString stringWithFormat:#"%#", text]
from:NO];
chatView.tag = WRITER_NAME_LABEL_TAG;
NSLog(#"MessageChatSelfCell->%#",chatView);
[cell addSubview:chatView];
}else {
chatView = (UIView *)[cell viewWithTag:WRITER_NAME_LABEL_TAG];
}
}
return cell;
}
I answered your another question How to calculate the Width and Height of NSString on UILabel
They are similar problem. the code below I C&P from the other question.
That's because you did not reuse the table cell, the structure should be like:
NSString *text = [messageInfo objectForKey:#"compiled"];
if(cell == nil)
{
writerNameLabel.numberOfLines = 0;
writerNameLabel.textAlignment = UITextAlignmentRight;
writerNameLabel.backgroundColor = [UIColor clearColor];
[cell addSubview:writerNameLabel];
}
else {
writerNameLabel = (UILabel *)[cell viewWithTag:WRITER_NAME_LABEL_TAG];
}
CGSize constraint = CGSizeMake(296,9999);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE]
constrainedToSize:constraint
lineBreakMode:UILineBreakModeWordWrap];
[writerNameLabel setFrame:CGRectMake(writerNameLabel.frame.origin.x, writerNameLabel.frame.origin.y, size.width, size.height)];
I've been gone through and answered some of your question, that's correct way to write your tableview controller. And your problem will be solved.
Few things u should change, first don't store your views in chatInfo instead store your data.
Next add the view to the cell only when u create new cell, otherwise u will add more then one view to a reused cell.
Take a look at the example below, here I'm creating a cell with the message writer name, for my messages the writer name will be in the right hand side, and for my friend messages it will be on the left.
Pay attention that I'm only add the writer name label when I create a new cell, then I give it a tag so I can get the label next time I want to change it.
#define WRITER_NAME_LABEL_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MessageChatFriendCellIdentifier = #"MessageChatFriendCell";
static NSString *MessageChatSelfCellIdentifier = #"MessageChatSelfCell";
UITableViewCell *cell = nil;
UILabel *writerNameLabel = nil;
NSDictionary *messageInfo = [self.chatArray objectAtIndex:indexPath.row];
BOOL myMessage = [[messageInfo objectForKey:#"myself"] boolValue];
if (myMessage) {
// this is my message
cell = [tableView dequeueReusableCellWithIdentifier:MessageChatSelfCellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MessageChatSelfCellIdentifier] autorelease];
writerNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 20)];
writerNameLabel.tag = WRITER_NAME_LABEL_TAG;
writerNameLabel.textAlignment = UITextAlignmentRight;
[cell addSubview:writerNameLabel];
}
else {
writerNameLabel = (UILabel *)[cell viewWithTag:WRITER_NAME_LABEL_TAG];
}
}
else {
// this is my friend message
cell = [tableView dequeueReusableCellWithIdentifier:MessageChatFriendCellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MessageChatFriendCellIdentifier] autorelease];
writerNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 20)];
writerNameLabel.tag = WRITER_NAME_LABEL_TAG;
writerNameLabel.textAlignment = UITextAlignmentLeft;
[cell addSubview:writerNameLabel];
}
else {
writerNameLabel = (UILabel *)[cell viewWithTag:WRITER_NAME_LABEL_TAG];
}
}
// get the current writer name from the model
NSString *writerName = [messageInfo objectForKey:#"writer"];
// configure cell...
writerNameLabel.text = writerName;
return cell;
}