I am updating my table data resource and then I am calling
[self.tableView reloadData]
to load the table view with this new data. This is all happening in a thread. Now, it works fine with lets say I add 4-5 objects but at some point it stops calling the cellForRowAtIndexPath to reload the table with new data.
Data source is getting updated all the time to contain latest data. So, data source has 10 objects but I can see only 5 on the screen. And it keeps on adding the data but do not show it. Breakpoint shows the call to reloadData is not invoking cellForRowAtIndexPath after that.
What could be the reason.
hunch: make sure you message UIKit objects from the main thread (exclusively).
Related
I have read several articles about UITableView, including the official doc and some on SO. But my situation seems to be different.
I want to update the Table each time the view loaded. And I must fetch the data using HTTP request.
What I got now is:
When enter the table view, I should use a non-synchronous HTTP request to update the data. Because I don't want the main thread to wait. One place to do that, is in the tableView:cellForRowAtIndexPath: method. So I return 0 for no data exist at the beginning.
When I get the HTTP respond, I update rows on main thread using beginUpdates endUpdates insertRowsAtIndexPaths:withRowAnimation:
And I must update the "Data Source" at the same time, but how to do that?
Or should I make a daemon thread and update my data every once in a while? So that the data will be ready when TableView is loaded.
You would do it like this:
Have a boolean or some variable where you can reliably detect whether you have all the data.
In viewWillAppear, reset everything. Start loading your data.
If you don't have the data yet, you only display one section with one cell (a placeholder cell that reads "Loading..." and shows a spinner, for instance).
Once the data is completely loaded, you set the bool or whatever.
Call [self.tableView reloadData];
In all of your UITableViewDataSource methods you would need to check whether you've got the data already or not. If not, you return the placeholder data.
[yourtablename reloadData]; will help you relaod the data in the tableview, You can call this once you get the response from your server
I'm not sure there's a "best method" for what you're trying to accomplish here. I would suggest trying the method you have, and seeing if it provides an adequate user experience (whatever that means to you) and if it doesn't, try something else. I would definitely suggest having some sort of "loading" indicator while the table is empty and waiting for http response.
In terms of your question about the "data source", the data source of a UITableView is simply an object that implements the UITableViewDataSource protocol which you can read about here. Often times, you will have XCode set up a UITableViewController object which will act as both delegate and data source to your table view. How you actually store your data is up to you. The data source protocol simply provides the methods by which a table view will "ask" for the data it needs to load.
I have a UITableViewController backed by a NSFetchedResultsController.
I'm currently experiencing a SIGABRT when deleting a row, after I save the managedObjectContext in commitEditingStyle.
The crash then happens in drawRect: in my UITableViewCell where it tries to access the core-data object for this row:
[self.document.name drawAtPoint:...]
The SIGABRT exception is:
<0x7f883f0 DocumentListControllerCell.m:(108)> CoreData could not fulfill a fault
for '0x7f2a600 <x-coredata://A71C21B4-FE2A-4D1B-A76F-A2AB80E4814C/Document/p16>'
Of course the issue is that the CoreData object has been deleted and cannot be accessed anymore. I wonder why drawRect is still called for this cell.
Any help would be appreciated!
when deleting a row also at that same time delete it from core data so that there is no redundant data that is being drawn.
Happened many times to me where i delete something from the table but not from where i was fetching the data and this would crash my app as it would draw the table properly when endcommit style was called.
So just make those changes and everything should be fine
PK
I see one solution but I would like to know if it's the correct way to solve this problem.
The issue currently is that drawRect in the cell access the CoreData "document" which was deleted, to get the document name and draw it. Instead of doing that, I could cache the document name in a string in setDocument and directly access this string.
It seems like it would be the right way to do that. Could someone confirm that I should not access the Core Data object in drawRect ?
I have a UITableView and I charged it with data in viewDidAppear. and it run successfully.
The Problem is I should refresh the data of the UITableView frequently (every 300 seconds).
So I defined a timer and charged the UITableView's dataSource when the timer throws the event of finishing time interval (300 secs).
BUT Nothing change !!!
The data stills as it was.
Any help would be appreciated.
Sorry for my english.
Try [tableView reloadData]
You don't fill the data actively, you just implement the data source delegates.
If the data has changed, use [yourTableView reloadData] to refresh, the table will fetch the data it needs. There are methods for reloading sections or a couple of rows, too, if you know what changed and want to animate this.
Also, make sure to call on the main thread (in case your timer fires on another thread).
I'm new to this Core Data business.
I got a UITableViewController hooked up with a NSFetchedResultsController. In viewDidLoad, I fire a request to get necessary data from the server, then use [self.fetchedResultsController performFetch:&error] to update the table view. All works fine until that point.
Now I want to move the data fetching stuff to another thread, so after the app received a NSArray object from the server, it performs the didFinishFetchingItems selector on the main thread. In that selector, I save the NSArray to the Core Data store and have the fetchedResultsController perform a fetch. No data show up, although a NSLog reveals that the data is still there (e.g. [[fetchedResultsController fetchedObjects] count] returns 100). I have to put a [self.tableView reloadData] at the end of the method to refresh the table view manually.
My question is: What have I done wrong? Why did I need to do the table view refreshing manually?
You should not touch your NSFetchedResultsController in a non-main thread, that is not a thread-safe operation.
If you are having a long delay on fetching then you need to do a background fetch using a separate NSManagedObjectContext. If you perform a separate fetch in the background it will load the data into cache and then the NSFetchedResultsController will hit the cache instead of disk, speeding up retrieval on the main thread.
You do not need to refresh anything manually; fetchedResultsController does that for you.
What you need to do is to implement NSFetchedResultsControllerDelegate for some object, and set that object as the delegate for your fetchedresultscontroller.
See this about what you need to implement. If your model is simple, you can pretty much copy-paste that code into your delegate and everything works.
The important thing is to keep both the resultscontroller and other pieces of code working against the same managed object context. This is how the resultscontroller can pick up the changes. But, in Core Data guide, there are some caveats about multithreading, so make sure you have your threading bases covered and then all works.
I have an array whose contents are updated and new entries are added on every seconds. How can i show the contents of an array in a table view so that i can see the newly inserted rows and updation of the added row.Can anyone help me.
Thanks in advance!!!
The answer suggested; [theTableView reload] definitely works fine. If you update the table every view seconds, however, your users will hate you.
Try to capture the reloading data in a notification handler. In that handler, check if the updated data belongs somewhere between the currently visible cells, if so, update the currently visible view. If not, ignore the updated data (but do add it to your underlying model). If the user scrolls further, after your update, cellForIndexPath: is called and the updated data will be drawn automatically.
reload is quite heavy to do every view seconds, certainly with a lot of data. drawing might get screwed up or worse..
You need to do a reload every time your datasource is updated. So if you table view is theTableView you would execute this instruction after your array is updated:
[theTableView reload]