data loading - app launching on tableview - iphone

i encounter an issue with my application.
On one hand when my app launches, the first view displayed is a tableview within a tableviewcontroller.
On the other hand my app calls a web service to collect data. These methods are in MyAppDelegate\applicationDidFinishLaunching.
The thing is that my tableview is made of custom cells that need data from the web service.
I noticed that the view (with the tableview) is launched first and then MyAppDelegate\applicationDidFinishLaunchin is executed.
As a result the labels of my custom cells are all equal to null as my arrays aren't filled yet by the web service.
I would like to know the proper way to make it.
If anyone has an idea please tell me.
Wallou

Use NSNotificationCenter to communicate to your UITableViewController that it needs to reloadData for the table.
To Register (in your UITableViewController.viewDidLoad):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dataLoaded:)
name:#"myapp.dataloaded" object:nil];
- (void)dataLoaded:(NSNotification *)notification
{
[self.table reloadData];
}
To post notifications (after you loaded the data):
[[NSNotificationCenter defaultCenter]
postNotificationName:#"myapp.dataloaded" object:nil];

Related

What's the better way to addObserver/removeObserver with NSNotificationCenter?

I used to addObserver in viewDidLoad: and removeObserver in dealloc:. Code:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshData)
name:AnyNotification
object:nil];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AnyNotification
object:nil];
}
But according to some articles said, it's better to addObserver in viewDidAppear: and removeObserver in viewDidDisappear:. Code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshData)
name:AnyNotification
object:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AnyNotification
object:nil];
}
So, what's the better way to addObserver/removeObserver?
this depends on your scenario, usually the best approach is to add in viewDidLoad and remove in dealloc and in viewDidUnload (deprecated in iOS 9.0, use dealloc only), but there are some cases when you have same method in different classes like UI effects and want to call only current screen's method using notification, then you will have to add the observer in viewWillAppear and remove it in viewWillDisappear or viewDidAppear/viewDidDisappear
Edit:
A note from comments, thanks #honey.
Though now since iOS 9, you no longer need to care about removing the observer. See Apple release notes: "In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated..
I would normally put it in -viewDidAppear: and -viewDidDisapear: (or -viewWillAppear: and -viewWillDisappear:) simply because in every case I came across I'm only interested in the notification if the view is actually displayed.
It's probably a premature optimisation (your code for handling the notification could take some time, but might be useless if the view is not displayed), but then it's also no more code - it's the same code just in a different method...
Don't forget NSKeyValueObservingOptionInitial. I use it with viewWillAppear/viewWillDisappear so my UI is always up-do-date, even if I hide that view controller, saving resources because I will not update it until is shown again.
The best approach using NSNotifications is adding the observer when you need to observe for notifications and remove them when you don't need them anymore.
This could be on viewDidLoad:, viewWillAppear:, or when the user taps some button etc.
I will give you a little example:
My app has a tabbar, and in some of the view controllers, I'm displaying some info downloaded from internet (a tweet for example). I also have a class pooling for new data from server each 2 minutes, and as the server had new data, I updated the info on database. I will not use a delegate pattern to listen to DB changes, because I have so many view controllers displaying data, and it will be a very bad design making the delegate an array and looping to pass the data for every view controller. So, in this specific scenario, the best to do is to post a notification telling every VC that new data has come.
If your VC removes the delegate when the view disappears, only the current one will receive the notification and update the displaying contents.
You obviously could update the contents of the other VCs before display, on viewWillAppear: for example, but doing this the VC contents will be updated not only when necessary, but each time you change tabs.
It was only one example, where I tried to show you that for NSNotifications, is difficult to advise you when to add or remove observers when we don't have the entire description of how you app behaviours.
-viewWillAppear: + -viewWillDisappear: is better than -viewDidAppear: + -viewDidDisapear:, because they are always called the same number of times.

update favourite list in realtime iphone

My app has two tabs, one of which is a table view, in the other tab I can add the current object to the core data storage, and I wish the table view could be up-to-date anytime I am done adding and switch back to that tab (table view). Currently, the table view only refreshes when my app relaunches which is understandable, because I am getting the data in the viewDidLoad method in that viewController. When I switch back and forth between these two tabs, their views are already loaded, so how can I update the table view in realtime? Any advice would be appreciated.
Update:
A good example is the contact app on iphone, but I don't know how to do that...
Here is some code in the table view controller.
- (void)viewDidLoad {
[super viewDidLoad];
bList = [[NSMutableArray alloc] init];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
//some code to get data from core data storage and put them in the bList array.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveAddNotification:)
name:#"AddNotification"
object:nil];
}
-(void) receiveAddNotification: (NSNotification *)notification{
if ([[notification name] isEqualToString:#"AddNotification"]){
NSLog (#"Successfully received the add notification!");
}
}
Code in the other tab's view controller.
-(IBAction) addSomething {
[[NSNotificationCenter defaultCenter] postNotificationName:#"AddNotification" object:self];
//some code to store an object in core data.
}
The console can output the message "Successfully received the add notification!", which means the notification works fine, but the table view didn't get refreshed when I switch back to the table view tab from edit tab. I'm assuming the newly added object in addSomething method should be updated to the receiveAddNotification: method either.
Hi Michael as I understand your question, You can use notifications concept. Start notification service in the table view controller and when you are done with adding the things you can post the notification so that, that will update the table view automatically.
Look in to the NSNotificationCenter.
Let me explain with an example.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:)
name:#"TestNotification"
object:nil];
add the above statement in the table view controller. Then you just define the "receiveTestNotification:" function with [tableview reload];
And in the editing view controller when user taps the done button you post the notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"TestNotification" object:self];
So it will call the "receiveTestNotification:" method and run the code what ever you gave in that method.

Reload table in model class

I have one view class. In this class I have table view. In my model class I make Asynchrous ASIHTTPRequest. And I want when the operation is successful to reload data in table view. Which is good way to do this. I consider add one UITableView property to model class and use reload it. Is this good approach?
Make your model post notification to NSNotificationCenter and your table view register for this notification and reloadData when it receives one.
Inside your model, when changes occur:
[[NSNotificationCenter defaultCenter] postNotificationName:#"uniqueNotificationName"
object:self];
Inside your table view controller, register for notification, for example in viewDidAppear:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(methodToCall:)
name:#"uniqueNotificationName"
object:nil];
And implement methodToCall:
- (void)methodToCall:(NSNotification *)notification {
[self.tableView reloadData];
}
When you are done with the table view, for example in viewWillDisappear: you need to unregister for notifications:
[[NSNotificationCenter defaultCenter] removeObserver:self];
I think your model should inform te controller that is has updated (or other way around using KVO). The controller should then message the view to reload.
When you want to reload table view you can use one of this approaches:
If you want to reload all displayed cells then you can just call [tableView reloadData];. Notice, that only displayed cells will be reloaded. So if you have, for example, 10000 cells and only 10 of them are displayed, then only for 10 cells will be recalled method cellForRowAtIndexPath:.
If you want to reload particular cells then you should call following method of UITableView : - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation and provide in first operand list of cells to reload.
If you want to reload whole section (or number of sections) of UITableView then you should call - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation and provide in first operand list of sections to reload.
Hope, it will help you to choose appropriate variant.
use synchrous and gcd to load data.
when receive data call [self reload] on main queue

Reloading TableView on iPhone from another class

So I have a FirstViewController, which is a UITableViewController, as well as delegate and dataSource. It has the table view.
I have another class, FeedParser, that parses the data - but after it's done parsing, I need it to go and refresh the UITableView or else it won't show anything.
This is probably a stupid question, so forgive me, but how should I go about calling FirstViewController's tableView.reloadData from FeedParser?
Is there a method to return that view?
Thanks!
Register the view controller to receive notifications that the data has been changed, and have it refresh the table when it receives one. Then have the parser send it out.
Registering for it is easy:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(yourRefreshMethodHere:)
name:#"YourNotificationName"
object:nil];
Your refresh method needs to be set up to receive these notifications, along these lines:
- (void)reloadTable:(NSNotification *)notif {
[self.yourTableName reloadData];
}
And it's important to stop observing in your ViewDidUnload:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Then in the parser you need to simply add this when it's complete:
[[NSNotificationCenter defaultCenter] postNotificationName:#"YourNotificationName"
object:nil];
The view controller (and anyone else observing the notification with that name) will get the message and perform its task.
Simple method,
Create a object for your FirstViewController in appDelegate, assign property and synthesize it.
In ViewDidLoad of FirstViewController,
firstViewControllerObj = self;
In feedParser.m, after the parsing done code as follows,
[appDelegate.firstViewControllerObj.tabelView reloadData];
Just store a reference to FirstViewController on your app delegate, then call [appDelegate.firstViewController.tableView reloadData].

Refresh view in iPhone navigation based application

I am using a navigation based application for iPhone. I want to reload a view when i come back to it after pressing the back button. ANy solution?
Regards
Add a method viewWillAppear: to your controller class. In that method you can then update the view with current data.
The viewWillAppear: method will execute whenever the view is about to be displayed (after navigating to a different view using UINavigationController)
There is more than one, but I usually use NSNotificationCenters. You attach "listeners" for some kind of event, like this:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(onSomethingChanged:)
name: #"somethingChangedEvent"
object: nil];
So, if some other view changes a setting, it notifies all the listeners like this:
[[NSNotificationCenter defaultCenter] postNotificationName: #"somethingChangedEvent" object: Nil];
Pretty simple and intuitive.