Well, the title already says it all. I have a view (a table view in my special case embedded in a non-table view controller) and at some time in code I want to update cells and display the update. The first part works like a charm but the changes won't displayed after the reloadData() - and even when I call setNeedsDisplay() afterwards.
When the controller has to update something the tableview will be also re-drawn and the changes are visible. As soon as I touch the tableview cell the changes are also visible. Without touch the update just isn't displayed.
I've come across this issue and using GCD should solve it
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
Related
I've been searching for a really long time but I found no answer for my question(s).
In my app I have a segmented control with two buttons.
When I toggle between those buttons I do:
Show a loading screen as a subview
do an url request to get the content to show in my tableview
fill my dataArray for my TableView with the new data
call reload data
remove loading screen subview.
In most cases everything works fine, BUT..
Sometimes, really not often, the table view "crashes", after this 5 steps. It means. The view only show one or two cells. And when I scroll to top or bottom I only scroll into white. In my current solution I can't reproduce this error on my iPhone(IOS6), only in simulator(IOS7). I think it has something to do with scrolling while changing the data of the table view. It only occurs while scrolling and pressing the segmented control button shortly after started scrolling, but only sometimes. But it could have another reason for sure..
My Question is, what could cause the table view to layout wrong (only displaying some cells correctly and scrolling into white), any Idea? And how can I recover/redraw the whole tableview after this happened? Please help..
I read a lot about [tableview beginUpdates],[tableview endUpdates] and insertRows, but I think this is not the right solution in this case. Or tell me if I'm wrong.
Here is the main code snipped for steps 2-4. If another part of code could help, maybe the cellForRowIndexPath, let me know.
NSMutableArray *newResults = [[NSMutableArray alloc] initWithArray:[self getResultsForRequest:url]];
[resultsLock lock];
results = newResults; //results is the data source for my tableView
[resultsLock unlock];
[self.tableView reloadData];
Thanks to all responders.
A question regarding reloading data in your UICollectionView.
When using reloadData it only does this once any scrolling has finished. Then there is a small pause where the collection view freezes and cannot be interacted with until the new data is loaded in. How can I get around this?
For example, I would have a view comprised of maybe 10/20/30 items, each with an image and label. I then update my dictionary with new images and strings and then reload the view to add these new items.
Many thanks.
EDIT:
On closer inspection, its not the reloading that causes the pause, its some other code, where I fetch some data. Why might this freeze my view though when i am not even reloading it to make changes to it?
I am fetching this data from -(void)scrollViewDidScroll:(UIScrollView *)scrollView
EDIT 2:
Ok here is some basic code
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self myMethodWithCompletionBlock:^(NSMutableDictionary *results, NSString *nextPageToken) {
//No code in completion block is ever called when the method is called in the dispatch block! Regardless of what it is.
}
});
I have a tab bar application that displays tableviews in two of the tabs. The tableviews are populated using NSFileManager to read the contents of a plist file stored with user data. One of the tabs displays the "complete" items, the other tab displays the "Incomplete" items. As the user selects a row, a page with the details of the item selected is displayed. In the incomplete table there is a button the user can press to move these details from the "Incomplete" table to a "Completed" table. The plist is then updated using NSFileManager to change a field detailing if the item is in the complete or the incomplete list for this item.
The problem I have is that the changes are not updated on the two tables just by selecting between the two tabs. The user has to quit the application and start it up again to see the item moved from one table to the other.
The data seems to be updated its just the view that doesn't update.
I'm new to cocoa so any help at all would be greatly appreciated.
As you haven't provided the code, so i cannot tell where exactly you should reload your tableview.
You have to call
[self.tableView reloadData];
just after you are finished using NSFileManager to save your data in the plist.
Table views are not updating because you are probably not calling [self.tableview reloadData]; when you call reloadData for a tableview it should update the tableviews.
Since you are using tab bar controllers when each view is pushed to the stack it stays there you need to detect if view is appear again and call reloadData method.
in completed.m add this:
-(void) viewWillAppear:(BOOL)animated{
[self.tableview reloadData];
}
in incomplete.m detect if NSFileManager is saved data then call [self.tableview reloadData];
there are also other ways to solve this problem, you can communicate between viewcontrollers via Delegate or NSNotifications pattern. So lets say you saved the data you call your delegate or NSNotification method and receiver view controller runs your desired method. In your case refreshes the tableview
How do I set up a simple delegate to communicate between two view controllers?
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_nsnotificationcenter/
A simple tableviewController, empty. A modal that can be launched from a button. No data in the data source for the tableview, and no rows displayed.
I open the modal, use it to add an item, and return to the tableview controller. The tableview updates itself automatically, and the new row is displayed.
I add a second item. The table view does NOT update automatically.
I can tell by logging inside numberOfSectionsInTableView that even if I go to add the first item and cancel, the tableview refreshes - it asks for the number of sections, rows, and the cell to display (if there is one). But not if there is one pre-existing row in the table.
I've scoured my code but can't find anything that would cause the tableview to know when the first item is added, but none afterwards.
Any ideas?
EDIT - I have further narrowed my issue so will close this shortly and have posted a more specific question at Why does an empty tableView check the number of sections but a non-empty one does not?
from Apple's documentation:
UITableView overrides the layoutSubviews method of UIView so that it
calls reloadData only when you create a new instance of UITableView or
when you assign a new data source.
maybe you are setting data source of table view after showing that modal? So at the second time data source does not changes and tableView does not update.
another key (I'm not sure about that) may be the showing of the modal first time. The method -addSubview for modal is causing -layoutSubviews.
In my application, I have a UITableView with a few rows (let's call it TV1), now, at the bottom of these rows is a row that drills down into another (TV2). This new TV2 asks you which type of data you would like to add to the first view. Then, when the user selects which kind, they're brought to another view, in which they fill in some fields, the data is saved, and they're sent back to TV1, however, the data they entered, isn't loaded and I'm not really sure how to do this. Any ideas?
Maybe you did this already, but how about using [TV1 reloadData];? This forces the entire table to reload, yet there are also more specific methods for reloading just the cells that have been altered. See also the documentation: UITableView
Reload your table view by calling [self.tableView reloadData] in the viewcontroller's viewWillAppear: method. It will be called when the user switches back to your view. Right before it is actually put on screen.