Let's assume there exists a UITableView called myTable. Let's say the following sequence of events occur --
Table is fully populated.
The data source is updated (in this case an sqlite3 db, but doesn't really matter), an NSNotifcation happens to indicate that there is new data, the main thread receives the notification and then calls [myTable reloadData].
myTable's UITableViewDataSource's numberOfSectionsInTableView gets called. Assume only 1 section.
myTable's UITableViewDataSource's tableView:numberOfRowsInSection: gets called.
Several tableView:cellForRowAtIndexPath:'s get called depending on the number of rows in the data source.
My question has to do with the interruptability of cellForRowAtIndexPath.
The question --
If a "reloadData" is called and cellForRowAtIndexPath's are getting called AND another reloadData comes in, will the cellForRowAtIndexPath's stop midstream and restart after the calls to numberOfSectionsInTableView and numberofRowsInSection?
Or will the new reloadData be queued, such that all of the cellForRowAtIndexPaths will finish BEFORE the numberOfSectionsInTableView and numberOfRowsInSection get called?
I've looked and have been unsuccessful in finding an answer to this question in docs or the net. I'm concerned that if the data store is updated while the cellForRowAtIndexPaths are "running", the numberOfSectionsInTableView can change which can result in the cellForRowAtIndexPath requesting data for a cell that's now out of range.
Any help would be greatly appreciated.
Since you should only call reloadData on the main thread and since by the time a call to reloadData is done, all of the visible cells have already been loaded, there is no problem to worry about. The second call to reloadData will be made after the 1st one is done.
I don't think it is possible to be in the middle of cellForRowAtIndexPath when reloadData is called assuming they are both called on the same (main) thread (having an async processing on background thread at cellForRowAtIndexPath seems meaningless).
Related
I have the following method on my table view controller class:
func reloadInputFields() {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.beginUpdates()
self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: .Automatic)
self.tableView.endUpdates()
}
}
This is called from an NSNotification. The runtime enters this method fine and appears to call reloadSections. However it never actually does. Obviously I am executing on the main thread here as it is a UI update but I have also tried on a background thread. I have also tried just calling tableView.reloadData() instead of reloadSections but no joy there. The table view definitely exists and I have checked that the pointer is correct.
Breakpoints in cellForRowAtIndexPath numberOfSectionsInTableView heightForRowAtIndexPath numberOfRowsInSection etc are not being hit and the table is not reloading.
My delegate and dataSource are set correctly as verified here:
I've been struggling with this for several hours now and it's totally bested me. Any suggestions would be gratefully received.
Some suggestions to solve this issue:
1. Make sure you have IBOutlet connection to the UITableView.
2. Check delegate and datasource. If necessary, write them programmatically.
3. Make sure your tableView is populated with data before triggering notification.
4. Avoid beginUpdates and endUpdates and use only reloadData on main thread.
Is the table view active when the notification is fired?
Check if the table view controller is released (It is not active. Probably not shown on the screen)
I want to access the visibleCells in scrollViewDidEndDecelerating, but I get an empty array. The reason is that I called reloadData and invalidateLayout shortly before in viewWillLayoutSubviews and it seems that both functions (scrollViewDidEndDecelerating and viewWillLayoutSubviews) are asynchronous. Even if want to get the visible cells, right after calling reloadData I get an empty array. So it has not been finished recalculating everything.
How do I know at which time/which method there are valid visible cells? Do I have to force everything running on the main UI thread or how do I run that in sync?
Edit:
My solution is to use another approach and don't use the visible cells for this.
My problem is as follows: At the first startup of my app the cellforRowAtIndex method doesn't load all items of an array, although the numberOfRowsInSection method gives right number of items, exp: numberOfRowsInSection method give 4 items but cellforRowAtIndex method loads only 2 items of these.
But at the second startup loads all items correctly, I hadn't found the reason of this problem, its just so annoying.
I have loaded all objects from an SSL Encrypted HTTPConnection to an array. I have debugged a few times with breakpoints already, but nothing found. The array is loaded with all objects already but cannot be loaded by cellforRowAtIndex method somehow.
Try to make sure that the table is updated after the array ends loading.
or just call [UITableView ReloadData]; after your array is fully loaded.
When you call -reloadData on a table view instance, does it make all UITableViewDataSource calls async?
Thank you.
This method actually just removes all the UITableViewCell views from the table. The data source delegate methods are called when the table is repainted.
So, it's asynchronous.
Edit:
Actually, some calls ARE synchronous. The number of sections & rows and row heights are updated immediately, so, for example contentSize is set correctly after the call. On the other hand, tableView:cellForRowAtIndex: is not called until the table is repainted.
I want to do a reloadData on a UITableView and after the table refresh is done, I want a delegate method to be called when I can know that the refresh is done. How do we know that ?
-reloadData blocks execution—your code won't continue past that call unless you're doing it on a separate thread. It should only be configuring nine cells or so at most; is there some reason you expect that to take a long time?