TableView not reloading from NSNotification - iphone

I'm having some trouble getting a tableView to reload using NSNotification.
My set up is that I have a filter view which allows the user to apply filters to the table view, once they click to change a filter I am sending an NSNotification which is picked up in the AppDelegate, this then reloads the core data applying the filters as a predicate.
Once the data has been loaded from core data I post another Notification to the tableView which tells it to reload it's data.
Using NSLog's I can see that the notifications are being sent and received although the [self.tableView reloadData] is doing nothing.
Here is my function to reload the data:
-(void)reloadTable:(NSNotification *)notification {
NSLog(#"reloading table");
[self.rootTableView reloadData];
}
Calling reload in the same way from inside the controller while it is currently in view works fine, so I'm pretty stuck as to why this isn't working.

Is the notification arriving on a thread other than the main thread? It would be if the notification were sent from a background thread. If this is the case, you'll need to marshall the reloadData call to the main thread. Something like this:
[tableView performSelectorOnMainThread: #"reloadData" withObject:nil waitUntilDone:NO];

This is for catching notification. You can put this in viewDidLoad.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserverForName:kSFAccountsChanged object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[tblView ReloadData];
}];
}
The code below will fire a notification:
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center postNotificationName:kSFAccountsChanged object:self];

1)
Have you attached your table to rootTableView in interface builder?
Try adding
NSLog(#"%#", self.rootTableView);
This should not be null :)
2)
If you have attached correctly, can you post the code in your table view delegate methods to see what's going on in there?

Related

Reload UITableView from another tab

I am having trouble trying to reload UITableView cell data which are being loaded from an XML source.
Here is the scenario. App contains tabs, in one of them there is a tableview which gets it's data from an XML file and works just ok, but the thing is when I want to change the feed category and change the XML from another tab I can refresh the current tableview.
For switching between tabs I use
self.tabBarController.selectedIndex = 1;
and pass the category feed to the other tab which I want to load
xmlParser = [[XMLParser alloc] loadXMLByURL:categories];
and it still loads the same old feed, not the new one which has been passed. I checked with NSLog and the feed value passes properly but it just wont load after switching.
I also tried to [self.tableView reloadData]; from both current tab and the category tab and it didn't work either.
You can use NSNotifications to send a notification from your other tab and have a oberver in your tableview that responds to that notification.
Example
(Tab calling the reload of the tableview) put this code whenever you want to reload the data, so when a button is pushed or a download is finished etc.
NSNotification * notification = [NSNotification notificationWithName:#"updateTable" object:nil];
[[NSNotificationCenter defaultCenter] postNotification:notification];
In the UITableViewController / the class with the UITableView, do the following.
in your viewDidLoad add:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateTableView) name:#"backtolist" object:nil];
Then add the function updateTableView
- (void) updateTableView: (NSNotification*) note
{
//Do whatever needs to be done to load new data before reloading the tableview
[_tableView reloadData];
}
Hope this helps
Ophychius was correct in his suggestion to use Notifications. I'm assuming you have all of the data sources for your table view updating when the XML is finished loading. This also assumes you're using dynamic cells. In the class that loads the XML, post a Notification when the new XML is finished loading.
[[NSNotificationCenter defaultCenter] postNotificationName:#"XMLLoaded" object:nil];
In the table view class, register as an observer for the Notification you posted from the XML class.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTable:) name:#"XMLLoaded" object:nil];
As you can see, this calls a selector when this notification is received. Either call your method where you build the table, or create another simple method to call reloadData from.
-(void)reloadTable:(NSNotification *)notif
{
NSLog(#"In ReloadTable method. Recieved notification: %#", notif);
[self.tableView reloadData];
}
Finally (as Leonardo pointed out below), in your viewDidUnload (or dealloc for ios6) method, remove the class as an observer of that notification.
- (void)viewDidUnload
{
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
I am just guessing, without having seen the rest of the code.
I suppose your table view has an NSArray datasource, did you make sure that your array datasource is updated too ? Does your xml parser, or controller, transfer those data to the NSArray ?
Because if you call reloadData it is just going to refetch the same array. And if it is not updated, you would get old data.

how to call function from another class and reload that view from the current class?

I am working on an application which uses bump technology.I do have four tab in which one is a table view .I wrote this bump API in app delegate class so that when the application is open it should be able to transfer the data.Transfer function is working properly.But the problem is that I am inserting the data into sq-lite and the data from sqlite is displayed in one of the tab bar item view.So when the user selects this tab bar item and receives the data i would like to insert and also reload the view with the new changes.As told before insertion i working.But the problem is reloading the view.Can any one help me with this problem?
You can perform insertion in background using NSOperation and post notification whenever you insert/edit a record. Add listener to the View controller where you are displaying data.
So whenever the controller receive the notification, it will call the method to reload data from database.
#implementation MyClass
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadData:) name:#"COREDATA_OBJECT_EDITED" object:nil];
return self;
}
- (void) reloadData:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"COREDATA_OBJECT_EDITED"])
{
//load records from database and reload tableview
}
}
#end
//Method where you are saving data objects in some other class
- (void) saveDataObject
{
//Save Data object, if saved successfully then post notification to listener to reload the data
// All instances of MyClass will be notified
[[NSNotificationCenter defaultCenter] postNotificationName:#"COREDATA_OBJECT_EDITED" object:self];
}

how to dynamically update table view in IOS?

i have a table and custom cells created dynamically, i have a http asyn call which gets me JSON data, now i need to update the table cells with the data received...
Call:
[self.tableView reloadData];
Have to NSNotification, one in the loadview and another one in the
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
delegate method , like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateTable) name:#"downloadCompleted" object:nil];
The above one in loadview method and the following one in the delegate
[[NSNotificationCenter defaultCenter] postNotificationName:#"downloadCompleted" object:nil];
the updateTable method will be called once data is obtained from JSON parsing. You can call the reloadData method of the tableview in this method to fill the tableview with obtained values.... Hope this helps.. Cheers...Happy coding..
call the table reloadData instance method . where ever you want to update the data of table.
Adding a bit more context using swift.
If you are trying to do this from a class that implements UITableViewController it will have a property tableView upon which you can call tableView.reloadData().
For example:
import UIKit
class TableViewController implements UITableViewController {
private func changeData() -> Void {
//... changes data
tableView.reloadData()
}
}
Source: UITableViewController

What's with [UITableView reloadData]?

I have an application that has a UITableView. This UITableView is populated by an NSMutableArray being held (as a property) in the appDelegate. You can think of this as an email window. It lists messages in a subclassed UITableViewCell. When a new message appears, I have all the code done which downloads the message, adds the data to the appDelegate's NSMutableArray which holds all of the messages. This code is working fine.
Now, once the new message is downloaded and added to the array, I am trying to update my UITableView using the following code, however - the UITableView's delegate functions do not get called.
The odd thing is when I scroll my UITableView up and down, the delegate methods finally get called and my section headers DO change (they show the message count for that section). Shoudn't they update in real-time and not wait for my scrolling to trigger the refresh? Also, the new cell is never added in the section!!
Please Help!!
APPDELEGATE CODE:
[self refreshMessagesDisplay]; //This is a call placed in the msg download method
-(void)refreshMessagesDisplay{
[self performSelectorOnMainThread:#selector(performMessageDisplay) withObject:nil waitUntilDone:NO];
}
-(void)performMessageDisplay{
[myMessagesView refresh];
}
UITableViewController Code:
-(void) refresh{
iPhone_PNPAppDelegate *mainDelegate = (iPhone_PNPAppDelegate *)[[UIApplication sharedApplication] delegate];
//self.messages is copied from appDelegate to get (old and) new messages.
self.messages=mainDelegate.messages;
//Some array manipulation takes place here.
[theTable reloadData];
[theTable setNeedsLayout]; //added out of desperation
[theTable setNeedsDisplay]; //added out of desperation
}
As a sanity check, have you verified that theTable is not nil at that point?
You could try putting a delay on the reloadData call - I had a similar problem when I was trying to get my tableview to update when reordering cells, except that the app crashed if I called reloadData during it.
So something like this might be worth a try:
Refresh method:
- (void)refreshDisplay:(UITableView *)tableView {
[tableView reloadData];
}
and then call it with (say) a 0.5 second delay:
[self performSelector:(#selector(refreshDisplay:)) withObject:(tableView) afterDelay:0.5];
Hope it works...
If you call reloadData from within a dispatched method, make sure to execute it on the main queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {
// hard work/updating here
// when finished ...
dispatch_async(dispatch_get_main_queue(), ^(void) {
[self.myTableView reloadData];
});
});
..same in method form:
-(void)updateDataInBackground {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {
// hard work/updating here
// when finished ...
[self reloadTable];
});
}
-(void)reloadTable {
dispatch_async(dispatch_get_main_queue(), ^(void) {
[myTableView reloadData];
});
}
Have you tried setting a breakpoint in your refresh method just to be sure your messages array has the correct content before calling reloadData?

Activity indicator in a UITabBar application on the iPhone

I have a UITabBar + UINavigationController application which often needs data from the internet. Sometimes it takes quite a while before it gets it, so I would like to show an activity indicator.
What I was trying is to add a activityView to my window in my applicationDidFinishLaunching method:
[window addSubview:tabBarController.view];
fullscreenLoadingView.hidden = YES;
[window addSubview:fullscreenLoadingView];
And then I add the application delegate as a observer to the default notification center:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(startFullscreenLoading:) name:#"startFullscreenLoading" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopFullscreenLoading:) name:#"stopFullscreenLoading" object:nil];
and implement the methods:
- (void)startFullscreenLoading:(NSNotification *)notification {
fullscreenLoadingView.hidden = NO;
}
- (void)stopFullscreenLoading:(NSNotification *)notification {
fullscreenLoadingView.hidden = YES;
}
When I then use this directly in the applicationDidFinishLaunching method the loading indicator view shows upp as expected:
[[NSNotificationCenter defaultCenter] postNotificationName:#"startFullscreenLoading" object:self];
But when I use it from one of the navigation controllers the startFullscreenLoading: method is called but I don't see the loading indicator view. Why is that?
Are you loading your data on a background thread? Your main thread will be blocked & won't be able to redraw or process any other events.
The most likely thing I can guess is that your indicator view is below some other view. Try
[[fullScreenLoadingView superView] bringSubviewToFront:fullScreenLoadingView]
If that doesn't work, I would suggest breaking inside of -startFullscreenLoading to make sure the fullscreenLoadingView is still valid.
In my app I did this by adding the UIActivityView in IB and making sure it was above everything else (as a top-level object). It's set to be invisible when stopped.
Then in my code I make it appear with [activityIndicator startAnimating] and make it disappear with [activityIndicator stopAnimating];