redoc01 redoc01 - 5 months ago 56
Objective-C Question

iOS, UITableView flashing after i reload new data

Whats Happening



I have a UITableView, what i do is display the first ten records from the database then when the user scrolls to the end i retrieve just one record from the database and then add this to the array and reload the data but the UITableView seems to flash. I have added some code that will sync the data correctly so that when i scroll down and retrieve the record i don't get duplicate data.

Question



How can i stop the flashing or flickering when i add new data to the UITableView?

CODE



This is where i add the new data when i scroll down to the bottom:

-(void)renderScrollThreadInfo:(NSDictionary*)dic{

NSDictionary *thread = [dic objectForKey:@"thread"];


if((NSNull*)thread != [NSNull null]){

int t_ID;
int t_U_ID;
int t_C_ID;
NSString *t_Name;
NSString *t_Description;
NSDate *t_Created;
int t_Flagged;
int t_Rated;
NSString *firstName;
NSString *lastName;
NSString *categoryName;

for(NSDictionary *dict in thread)
{
if((NSNull *)[dict objectForKey:@"T_ID"] != [NSNull null]){
t_ID = [[dict objectForKey:@"T_ID"] intValue];
}
if((NSNull *)[dict objectForKey:@"T_U_ID"] != [NSNull null]){
t_U_ID = [[dict objectForKey:@"T_U_ID"] intValue];
}
if((NSNull *)[dict objectForKey:@"T_C_ID"] != [NSNull null]){
t_C_ID = [[dict objectForKey:@"T_C_ID"] intValue];
}
if((NSNull *)[dict objectForKey:@"T_Name"] != [NSNull null]){
t_Name = [dict objectForKey:@"T_Name"];
}
if((NSNull *)[dict objectForKey:@"T_Description"] != [NSNull null]){
t_Description = [dict objectForKey:@"T_Description"];
}
if((NSNull *)[dict objectForKey:@"T_Created"] != [NSNull null]){
NSString *timestampString = [dict objectForKey:@"T_Created"];
double timestampDate = [timestampString doubleValue];
t_Created = [NSDate dateWithTimeIntervalSince1970:timestampDate];
}
if((NSNull *)[dict objectForKey:@"T_Flagged"] != [NSNull null]){
t_Flagged = [[dict objectForKey:@"T_Flagged"] intValue];
}
if((NSNull *)[dict objectForKey:@"T_Rated"] != [NSNull null]){
t_Rated = [[dict objectForKey:@"T_Rated"] intValue];
}
if((NSNull *)[dict objectForKey:@"U_FirstName"] != [NSNull null]){
firstName = [dict objectForKey:@"U_FirstName"];
}
if((NSNull *)[dict objectForKey:@"U_LastName"] != [NSNull null]){
lastName = [dict objectForKey:@"U_LastName"];
}
if((NSNull *)[dict objectForKey:@"C_Name"] != [NSNull null]){
categoryName = [dict objectForKey:@"C_Name"];
}

ThreadInfo *threadObj = [ThreadInfo new];
threadObj.iD = t_ID;
threadObj.userId = t_U_ID;
threadObj.catId = t_C_ID;
threadObj.name = t_Name;
threadObj.description = t_Description;
threadObj.timeStampCreated = t_Created;
threadObj.flagged = t_Flagged;
threadObj.rated = t_Rated;
threadObj.firstName = firstName;
threadObj.lastName = lastName;
threadObj.category = categoryName;

BOOL foundThreadId = false;

for(int i = 0; i < [threadsArray count] - 1; i++){
ThreadInfo *tmpThreadInfo = (ThreadInfo*)[threadsArray objectAtIndex:i];
if(tmpThreadInfo.iD == t_ID){
foundThreadId = true;
}
}

if(!foundThreadId){
[threadsArray addObject:threadObj];
}



}
[tableViewThreads reloadData];
}

}


This is the code that calls a php script to get the next record:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableViewThreads == tableView){
//NSLog(@"%d %d",[indexPath row], [threadsArray count] - 1);
if ([indexPath row] == [threadsArray count] - 2) {

ThreadInfo *threadInfo = (ThreadInfo*)[threadsArray objectAtIndex:[threadsArray count] - 1];
int tid = threadInfo.iD;


dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 3) Load picker in background
dispatch_async(concurrentQueue, ^{


NSString *searchItem = textFieldSearchThreads.text;
NSString *myRequestString = [NSString stringWithFormat:@"Category=%d&TID=%d&SearchItem=%@",rowCategory, tid, searchItem];
NSString *response = [self setupPhpCall:myRequestString :@"getThread.php"];


dispatch_async(dispatch_get_main_queue(), ^{

if(response.length > 0){
[self renderScrollThreadInfo:[response JSONValue]];
}

});

});
}
}

if(tableViewPosts == tableView){
//NSLog(@"%d %d",[indexPath row], [threadsArray count] - 1);
if ([indexPath row] == [postsArray count] - 1) {

PostInfo *postInfo = (PostInfo*)[postsArray objectAtIndex:[postsArray count] - 1];
int pid = postInfo.iD;


dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 3) Load picker in background
dispatch_async(concurrentQueue, ^{


NSString *myRequestString = [NSString stringWithFormat:@"TID=%d&PID=%d", chatThreadId, pid];
NSString *response = [self setupPhpCall:myRequestString :@"getStandalonePost.php"];


dispatch_async(dispatch_get_main_queue(), ^{

if(response.length > 0){
//[tableViewPosts scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
[self renderScrollPostInfo:[response JSONValue]];
}

});

});
}
}
}


This is the code where a set up my Custom Cells with data:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


if(tableViewThreads == tableView){
NSString *cellIdentifier = @"cell";
ThreadTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];


ThreadInfo *threadInfo = (ThreadInfo*)[self.threadsArray objectAtIndex:indexPath.row];;
if (cell == nil)
{
cell = [[ThreadTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];

[cell setupView:threadInfo];

}


cell.labelFirstName.text = [NSString stringWithFormat:@"%@ %@", threadInfo.firstName,threadInfo.lastName];

cell.labelTimestamp.text = [NSDateFormatter localizedStringFromDate:threadInfo.timeStampCreated dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
cell.labelTimestamp.text = [cell.labelTimestamp.text stringByReplacingOccurrencesOfString:@"AM" withString:@""];
cell.labelTimestamp.text = [cell.labelTimestamp.text stringByReplacingOccurrencesOfString:@"PM" withString:@""];

cell.labelThreadName.text = threadInfo.name;
//cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;

}
if(tableViewPosts == tableView){
NSString *cellIdentifier = @"cell2";
PostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

PostInfo *postInfo = (PostInfo*)[self.postsArray objectAtIndex:indexPath.row];
if (cell == nil)
{
cell = [[PostTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];

[cell setupView:postInfo];
}



cell.labelUserName.text = [NSString stringWithFormat:@"%@ %@ posted...", postInfo.firstName,postInfo.lastName];
cell.labelCreated.text = [NSDateFormatter localizedStringFromDate:postInfo.timeStampCreated dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
cell.labelCreated.text = [cell.labelCreated.text stringByReplacingOccurrencesOfString:@"AM" withString:@""];
cell.labelCreated.text = [cell.labelCreated.text stringByReplacingOccurrencesOfString:@"PM" withString:@""];
cell.labelMessage.text = postInfo.message;
return cell;
//[cell.contentView addSubview:[self setupThreadItem:threadInfo]];
}

return nil;
}

Answer

Instead of calling [UITableView reloadData] when you receive new data, use [UITableView insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

Comments