reloadRowsAtIndexPaths block user interface - ios

i have an iOS app with UITabbarController, and in one tab view there is a UITableViewController, when i switch tab i what reload the visible cell row because the row contain a UILabel with time and i want refresh the time with the passage of time, but when i tap the tab with the UITableView, i use this code:
NSArray *visible = [self.tableView indexPathsForVisibleRows];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:visible withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
and i call it in ViewWillAppear, and with this code takes a moment to open, is not immediate, and with out it is immediate. So how i can refresh that rows without block the UI?

Putting the code in ViewWillAppear: means it gets run before the view has appeared. Since you want animations that the user will see, it makes sense to move this code into ViewDidAppear
Don't forget to call [super viewDidAppear]!

Related

UITableView's selectRowAtIndexPath:animated:scrollPosition: not working after reloadData in iOS 8

I have the following code in tableView:didSelectRowAtIndexPath:
[tableView reloadData];
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
It deselects a table view cell tapped by the user (with animation) after the table view is reloaded. It has worked fine in iOS 7 and earlier, but in iOS 8 the animation isn't shown.
What changes were made in iOS 8 to cause this? And what's the best way to achieve the same effect in iOS 8?
What is the surrounding code that's causing you to call [tableView reloadData]?
Depending on how much processing you are doing in cellForRowAtIndexPath and the surrounding methods, this can be an expensive operation.
You can run:
[tableView beginUpdates];
// Update code here
[tableView endUpdates];
without having to reload the entire tableView datasource.
When didSelectRowAtIndexPath is called, the cell is already selected. So there shouldn't be any need to call the tableView's selectRowAtIndexPath method. Simply calling deselectRowAtIndexPath should do the trick after updating your cells

Execute a method right after tableview delegate methods

I wanted to highlight a particular row in a tableview(even after refreshing the values in it). But each time when I refresh the table using
[tableView reloadData]
the highlighted selection is gone.
-(void) loadValues {
[tableView reloadData];
[self displaySelection];
}
When I checked the flow of execution, I found out that only after the displaySelection method, the tableView's delegate methods are executed.
I've used a variable as a flag to check for the last row in the 'cellForRow' method to solve my problem. But I really wanted to know is there any other way to check that the tableView's delegate methods are executed completely so that 'displaySelection' will be executed only after it.
Try using something like:
[tableView performSelector:#selector(reloadData) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
This should actually block your thread until the tableview gets reloaded.

Row deletion does not refresh table view in ios app

I have spent hours searching for the solution with out any luck. I am trying to delete a row (also deselect same row) programmatically. After row deletion call below, UITableViewDelgate methods get called expectedly and data source is updated but UITableView is not refreshed. deselectRowAtIndexPath call also does not work. I tried all kinds of scenarios as shown by commented lines.
Here is my code:
checkoutPerson is called as a result of observer listening for NSNotificationCenter messages.
- (void) checkoutPerson: (NSNumber*) personId {
Person *person = [_people objectForKey:personId];
if( person )
{
// Remove person from data source
int rowIndex = person.rowIndex;
S2Log(#"Deleting row number=%d", rowIndex);
[_allKeys removeObjectAtIndex:rowIndex];
[_people removeObjectForKey: personId];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
//[[self tableView] beginUpdates];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
S2Log(#"Deleting indexPath row=%d", [indexPath row]);
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
//[[self tableView] endUpdates];
S2Log(#"Reloading data");
//[[self tableView] reloadData];
//[self performSelector:#selector(refreshView) withObject:nil afterDelay:1.5];
//[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
}
I will appreciate for help.
Thanks
-Virendra
I believe deleted cell is not being recycled. If I delete row in the middle, last row is always erased (since there is one less item) but the deleted row remains.
Use the above code between two function for table view
[tableView beginUpdates];
// the deletion code from data source and UITableView
[tableView endUpdates];
By calling this functions you are telling UITableView that you are about to make updates for deleting your cell.
Edit
The other problem I see with your code is you first delete the data from the data source.
Now you are asking for the UITableViewCell (which actually reloads the UITableView)
and then you are deleting the row from UITableView
I guess you should fetch the UITableViewCell before deleting values from your data source.
I found the problem. It has nothing to do with the code I posted above. It is syncing problem between visual display and the contents of data source. I have an embedded UITableView as part of a composite view. In composite view's controller, I was wiring up UITableView's delegate and data source to an instance of UITableViewController. Instead of this, I should have set UITableViewController's tableView property to the embedded UITableView. It seems that UITableView has to be contained within UITableViewController in order to correctly sync up table view visual display to the contents of data source. This also fixes row deselection and scrolling. I also needed to delay reloadData call in which case deleteRowsAtIndexPaths:withRowAnimation is not required. All you need is to modify the contents of your data source and call reloadData with a delay of 1.5 Seconds.
Thanks to all for great help.

tableviewcontroller within container view controller: programatically selecting uitableviewcell, highlighting blinks

I am trying to programatically highlight a table view cell and trigger the selection logic by doing the following
NSIndexPath*indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
The row highlights only for a split second. I want it to stay highlighted until I select another row.
I tried adding these lines
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath: indexPath];
cell.highlighted = YES;
but when I did this, the highlight remained even when I clicked on another row and did not go away until I clicked the first row again.
Any ideas?
Try calling selectRowAtIndexPath but not didSelectRowAtIndexPath. I believe the latter is called as a result of the former. If your delegate deSelects the last selected index path in didSelectRowAtIndexPath, then the double call would result in deselecting what you had just selected
seems like the issue was because I was calling the code from viewDidLoad, I moved it to viewDidAppear and now its fine

UITableView value not rendering until screen is re-rendered

I have a table view with a detail label on the right. This label is populated by a entity that I populate from a JSON call in my connectionDidFinishLoading function. The problem is that the cellFromRowAtIndexPath function fires before the connectionDidFinishLoading function so I don't see the values in my table view until I pull down on the screen which redraws the page. I have tried refreshing the table view at the end of both of these functions but that doesn't see to work. Can someone give me a clue as to why this is happening and how I can fix it please.
you have to reload your table data at the end of your connectionDidFinishLoading.
two ways:
The first:
[tableView reloadData];
The second:
NSArray* rows = [tableView indexPathsForVisibleRows];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:rows withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
Are you calling reloadData in the main thread? connectionDidFinishLoading sounds like it's running in a background thread.
After populating, call reloadData on the tableView.
This should do it. All UI updates and manipulations must be performed from the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});

Resources