Reload table in model class - iphone

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

Related

Passing data to parent viewcontroller from tableviewcontroller

so currently I have a tableviewcontroller that gets presented modally above the loginviewcontroller if a certain case occurs, then once the user presses on a cell, the title should be passed to the parent view controller.
So picture (A) being the parent - the mainview, (B) being the login, and (C) being the tableviewcontroller...
C sits on top of B which sits on top of A, NOT THROUGH A NAVIGATION STACK BUT THROUGH A MODAL STACK. So C doesn't have any reference to A other than this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self Login];
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
When a user presses on a cell, the view then goes straight to (A), so from (C) to (A) skipping (B). This is what I wanted... But the issue is how do I pass data to (A) without having to instantiate (A) again? I mean instantiate again by, it's already instantiated in the beginning of the app launch and (B) is presented over (A) if the user isn't already logged in. So (A) is ALWAYS loaded, but how do I pass data to it?
If there is more information that should be provided, please inform me and i'll edit ASAP.
EDIT
I looked at a few more questions that related to this one, would I use NSNotification? Or delegation? I attempted to use both but none really worked... I refered to my previously answered question on delegation to implement the delegation solution but I have to instantiate (C) in (A). But I already instantiate (C) in (B). Heres the delgation solution I was gonna use but didn't: Delegation. Here is the Link for the NSNotification solution i attempted to use:
Put this in your parent controller in viewDidLoad
- (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self makeCallbacks];
// get register to fetch notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(yourNotificationHandler:)
name:#"MODELVIEW DISMISS" object:nil];
}
//Now create yourNotificationHandler: like this in parent class
-(void)yourNotificationHandler:(NSNotification *)notice{
str = [notice object];
}
Put following to your child class where
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"%#", cell.textLabel.text);
// cell.textLabel.text logs this -> EDF ENRS
[[NSNotificationCenter defaultCenter] postNotificationName:#"MODELVIEW DISMISS" object:cell.textLabel.text];
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
When I log 'str' (null) is printed
Now the issue is when I log str outside of the notification later in viewWillAppear, it keeps returning null.... It only DOESNT return null when I log str within the notification method... I'll try to figure this out later but the primary issue is i guess solved using NSNotificationCenter.
The problem behind the NSNotificationCenter not working, is with it being declared in viewDidAppear.
Make sure, its appearing and written somewhere where the changes are made , everytime the screen is displayed, like viewWillAppear.
And then, make the necessary changes to the parentView, in this viewWillAppear method.
Also, be sure to remove the notifications, inside the methods that are called, when those notifications are posted.
Your notification code should work, unless you're removing the observer at some point in time.
Delegation will also work, you just need to pass the delegate down through the instances (A pass to B, B pass on to C).
Blocks are another option, similar to delegation but with a block type instead of a protocol. Again, passed down through the instances.
Blocks are probably your best option. Notifications should be used where multiple items are interested in the event and those items aren't necessarily associated with the trigger of the event. That said, notifications are the 'least code option'.

Kill a view/View controller from memory from another View Controller

I am fairly new to Obj-C programming, so please bear with me.
I have a Tab Bar. 1 of the tabs has a table view controller that gets it's data from an SQL database into an array.
In another tab it has a button to reset everything (delete all data). The view controller for this tab successfully deletes the SQL database, however the table is still full of data when going back to the table tab.
How can I unload the table view controller from memory when the button is pressed from this other view controller?
If I simulate a memory warning, then the table clears and is rebuilt when going back to the tab. This is what I am trying to do in code.
Thanks
You need to call reloadData on that UITableView.
It is cleared during memory warning, cause a view controller recreates its own view every time it receives this warning (in case it is not currently visible).
I think you could accomplish this using NSNotifications.
In the init method of your 1st view controller put this code:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(tableViewDataUpdated:)
name:#"DATA_UPDATED"
object:nil];
Create a tableViewDataUpdated method that reloads the array containing the data, and then calls reload on the table view.
In the 2nd view controller, when sql data base gets cleared, call
NSNotification *notification = [NSNotification notificationWithName:#"DATA_UPDATED" object:nil userInfo:nil];
[[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
Finally in the dealloc method of the 1st view controller include:
[[NSNotificationCenter defaultCenter] removeObserver:self];

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].

data loading - app launching on tableview

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];

iPhone UITableView trigger a parent method?

Okay, so I'm working on an iPhone app with a preferences-esque section where there's a base TableView, which has one section, and several rows of customized cells to hold a name and a value label. Clicking on a row brings up another View, which allows the user to pick from a list (another TableView), and select an item.
All of these TableViews are done programatically. The base TableView has a property that holds a Controller instance for each of the "pick from the list" Views. Each of the "pick from the list" views has a property called chosenValue that has the currently-selected option. I've gotten the UI to handle the didSelectRowAtIndexPath to update the chosenValue property and then "pop" the view (going back to the main TableView). But, even though the main TableView's cellForRowAtIndexPath method references the chosenValue property of the subview that's held in a property, the view doesn't update when an item is selected. In short, how can the sub-view trigger a reloadData on the parent object, after it "pops" and unloads?
You could realize this using the notifications or delegation, for example.
Using notifications your first view controller has to register for a notification like this:
…
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(methodToBeCalled:)
name:#"myNotification"
object:nil];
…
- (void)methodToBeCalled:(NSNotification *)notification {
[self.tableView reloadData];
// do something else
}
Then you can raise a notification in your second view controller like this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:nil];
Using delegation you could implement a property for a delegate on the second view, set that to self before pushing the second view controller and call a method on the delegate when needed.
You should define a delegate for that.
In the child TableView define a protocol:
#protocol ChildViewControllerDelegate
- (void) somethingUpdated;
#end
Also define a property for a delegate implementing this protocol:
id <ChildViewControllerDelegate> delegate;
Then in Parent all you need to do is to define a method somethingUpdated, assign itself (parent) to a delegate property in Child and call this method in Child view when you need to update it. Implementation of somethingUpdated in Parent can be different based on what you're trying to accomplish.
flohei thanks so much for posting this!! I got it working with NSNotificationCenter! I have a child view calling a method in a parent view now! Awesome. #sha I tried your protocol way also but could not figure it out. Perhaps a more illaborate discription would help a noob like me. I have been reading that your protocol way is the better cause I guess less code? So i'll try to keep learning it. Thanks to you both!