UITableView Cell Data is Repeating When Paging - Objective C - ios

I am using Objective C and Parse. I have a UITableView that displays photos from Parse. The first 10 cells load then you can tap load more for the next 10 cells and so on. My issue is in the same class that I am getting the photo, I also want to display the caption column. The first 10 cells show the caption correctly, it's when I page to the next 10 cells that the captions start repeating. The photos do not repeat so I'm not sure why the captions do. Below is my code that loads the UITableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
if (indexPath.section == self.objects.count) {
// this behavior is normally handled by PFQueryTableViewController, but we are using sections for each object and we must handle this ourselves
UITableViewCell *cell = [self tableView:tableView cellForNextPageAtIndexPath:indexPath];
return cell;
}
else {
ESPhotoCell *cell = (ESPhotoCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ESPhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.mediaItemButton addTarget:self action:#selector(didTapOnPhotoAction:) forControlEvents:UIControlEventTouchUpInside];
}
cell.mediaItemButton.tag = indexPath.section;
//The below line of code displays the black square where the photo would be.
cell.imageView.image = [UIImage imageNamed:#"PlaceholderPhoto"];
if (object) {
//The below line displays the users photo on the timeline.
//The following 2 lines is what fills the display cell that shows the photo.
cell.imageView.clipsToBounds = YES;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
//The below line is what displays the image on the home timeline.
cell.imageView.file = [object objectForKey:kESPhotoPictureKey];
[cell.imageView loadInBackground];
//Below is what I am trying to display the captions
NSString *caption = [object objectForKey:#"caption"];
if (caption != nil) {
cell.captionText.text = [object objectForKey:#"caption"];
}
}
return cell;
}
}
Any help to this issue would be appreciated as I am fairly new to mobile development.

Related

UITableview duplicate Images by scrolling

I have the following behavior: i have a table with number of rows = 20
i have created in Storyboard UITableView Cell with UIImage.
I use the function didSelectRowAtIndexPath for show and hide a image. If i select a row the UIImage xxx.png will be displayed. If i select the same row again then the Image is hidden. That works perfekt but when i scroll down i see rows with images and i have no selected this rows.
I will only see the image when i select a row and not duplicates wehen i scroll the table.
Here is my code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WorkoutTableVCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WorkoutCell" forIndexPath:indexPath];
cell.checkImage= nil;
if (cell == nil)
{
cell = [[WorkoutTableVCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"WorkoutCell"];
}
else{
//Old cell...get previously createdd imageview
cell.checkImage = (UIImageView*)[cell.contentView viewWithTag:1001];
}
long row = [indexPath row];
cell.lblCell.text = _MyValues[row];
return cell;
}
I hope you can understand my problem and sorry for my bad english :(
Cells are reused, so you need set the image of the cell each time. You need to have another data source that contains images for each indexPath and use that to set the image for the UIImageView in the cell.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
WorkoutTableVCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WorkoutCell" forIndexPath:indexPath];
if (cell == nil)
{
cell = [[WorkoutTableVCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"WorkoutCell"];
}
long row = [indexPath row];
cell.lblCell.text = _MyValues[row];
// set the image for the UIImageView here
cell.imageView.image = _MyImages[row];
return cell;
}
An even better approach would be to have your data source be a key/value pair (like a NSDictionary) with the Keys being the text that goes in the label and the value being the image that should be assigned to the UIImageView.

After searching filtering in tableview, why it shows blank cell?

Now I have a dynamic cell to show lists. And Using Search Bar and Search Display Controller. Why it shows blank on simulator.
Before filtering,the simulator shows all cells and disclosure could link to another table view. After filtering, it should show some of cells. But it is blank. And the disclosure is not worked as well.
Codes for cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"MovieCell";
MovieCell *cell = (MovieCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Movie *movie = nil;
if (cell == nil) {
cell = [[MovieCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
movie= [filteredMovieArray objectAtIndex:[indexPath row]];
} else {
movieArray = self.movies;
movie = [movieArray objectAtIndex:[indexPath row]];
}
cell.nameLabel.text = movie.movieName;
cell.placeLabel.text = movie.place;
cell.categoryLabel.text = movie.category;
cell.isFavLabel.text = movie.isFavourite ? #"Favourite" : #"Not Favourite";
[cell.starRating setRating:movie.rating];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
NSLog(#"description = %#",[cell description]);
return cell;
}
I made it. I think this is a good answer for it: Search Bar in UITableView doesn't display text in Cell label.
What's more, I also add this code section to fit the cell height:
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
tableView.rowHeight = 87;
}
This number is the row height of my cell.

UITableViewCell Doesn't display loaded data but displays it when selected

I am facing a weird issue and I am sure I am doing something wrong. In my UITableViewController class I have a function as follows:
-(void)EERefreshView
{
NSLog(#"App delegate requested the view be refreshed");
[self loadEventsFromDB];
for(int a=0;a<eventsList.count;a++)
{
DB_EEEvent *event = (DB_EEEvent*)eventsList[a];
UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
//NSLog(#"CellID %#", cell.reuseIdentifier);
//get references to the UI components
UILabel *lblTitle = (UILabel*)[cell.contentView viewWithTag:5];
UILabel *lblDate = (UILabel*) [cell.contentView viewWithTag:6];
UIImageView *imgEvent = (UIImageView*)[cell.contentView viewWithTag:7];
//set values
lblTitle.text = event.name;
lblDate.text = [NSString stringWithFormat:#"%# - %#",
event.startdate,event.enddate];
AppDelegate *del = [AppDelegate sharedAppDelegate]; //need this to get the BaseURL
// Here we use the new provided setImageWithURL: method to load the web image
NSString * imageURL =[[NSString alloc] initWithFormat:#"http://%#%#",del.api.BaseURL,event.logo];
NSString* webStringURL = [imageURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:webStringURL];
[imgEvent setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
//do somethign when image call completes
}];
[eventsListCells addObject:cell];
if(a == selectedEvent)
{
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[tblEventsList reloadData];
});
}
This function loads an array with UITableViewCell objects which is then used later on by
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell data
NSLog(#"IndexPathRow: %d", indexPath.row);
UITableViewCell *cell = (UITableViewCell*)eventsListCells[indexPath.row];
return cell;
}
However when the cell is loaded lblTitle and lblDate have no text displaying in them. But when I tap on a cell it then displays the text in the labels. So this means that the data is there but its not being refresh when initially created. I suspect this might have something to do with threads but I am not an expert on the subject and would appreciate any help that I can get.
I see what is bothering you and why you created this method, but you don't need it. The only reason why you need back thread is your image loading so that should be thrown in bkg. thread and the rest of the code should be in -
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
U really don't need to pre create cells, and U cant cause they are reusable. For example if you have 50 elements in eventsList and room for only 5 cell on your screen you cant create 50 cells cause the code will create only 5+1 and reuse them as they appear on the screen, so every element of your eventsList will use one of those 5 cells and on the other side every cell will be a host for 10 different elements from your eventsList array. So as you can see your code doesn't make much sense...
The second function you mentioned in your question is the function that is called to populate the table with data. When you call [tblEventsList reloadData]; your app just calls the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. So this method needs to be outputting data back to the table. A very simple example is below. Also, make sure your table delegate and data source are set.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell.
cell.textLabel.text = [self.your_data_source objectAtIndex:[indexPath row]];
return cell;
}

UITableViewCell imageView problems

I have a custom leaderboard which I load Game Center profile pictures into a UITableCell that is 32 high.
What happens is when I set the image it displays at around 200x32 then quickly resizes to be a square. The user sees a flash where the image is distorted before it is shown properly.
What is happening here? How can I fix this?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([GCCustomLeaderboard sharedInstance]->nearbyScores.count == 0){
return nil;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyBasicCell"];
GCLeaderboardScore *playerScore = [[GCCustomLeaderboard sharedInstance]->nearbyScores objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#: (%d)", playerScore->alias, (int)playerScore->score];
cell.imageView.image = playerScore->photo;
return cell;
}
To fix this I had to resize my images BEFORE putting them in the table.

Different UITableView scrolling performance on iPad 2 & iPhone 4s

Solved
There was a shadow on the self.view layer. After removed it, the tableview scrolls smoothly (56-59fps).
The problem I got is so weird.
I am building a UITableView based Twitter like App. After optimized the table view loading and scrolling, I tested the App (same code & same UI) on both iPad 2 and iPhone 4S. On the iPad 2, I got 56-59fps smooth scrolling animation. But on the iPhone 4S, I got only 43-49fps scrolling animation, which is awful.
This seems not caused by the Retina display. After I remove all images from cells, the problem is still there. The following is the code of cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// fetch note from the fetched results controller
Note *note = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([note.photos count] > 0) {
static NSString *CellIdentifier = #"Photo Cell";
PhotoCell *cell = (PhotoCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} else {
[cell clearContents];
}
NSNumber *currentRowNumber = [NSNumber numberWithInt:indexPath.row];
// check if the photos of this cell has been pre loaded
NSDictionary *coverImages = [self.coverImagesForNotes objectForKey:currentRowNumber];
if (coverImages == nil) {
if (self.tableView.dragging == NO && self.tableView.decelerating == NO) {
coverImages = [self loadCoverImagesForCell:indexPath photos:note.photos];
[self.coverImagesForNotes setObject:coverImages forKey:currentRowNumber];
}
}
// assign contents to the cell
[self compositeContentView:cell forNote:note rowNumber:indexPath.row];
// refine
unsigned textContentHeight = [[self.cellTextHeightDict objectForKey:currentRowNumber] integerValue];
unsigned currentPageNumber = [self currentPageNumberAtRow:indexPath.row];
[cell initPhotoVideoView:textContentHeight photos:note.photos coverImages:coverImages showPage:currentPageNumber rowNumber:indexPath.row];
cell.delegate = self;
return cell;
} else {
static NSString *CellIdentifier = #"Simple Cell";
BaseCell *cell = (BaseCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[OneViewBaseCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// assign contents to the cell
[self compositeContentView:cell forNote:note rowNumber:indexPath.row];
return cell;
}
}
Thanks for answers.
Are you using images in your table view cells? This will be more expensive on a retina display. Also if you are using images, try to load them in on a background thread which will reduce the latency.
If you're not using images then you should really look at how you are creating your cells, please post tableView:cellForRowAtIndexPath: method implementation

Resources