Reputation: 2307
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.
How can i stop the flashing or flickering when i add new data to the UITableView?
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;
}
Upvotes: 1
Views: 1146
Reputation: 41226
Instead of calling [UITableView reloadData] when you receive new data, use [UITableView insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
Upvotes: 3