Using KVO to reload data in UITableView - iphone

I've been expanding my horizons recently and am trying to start utilizing KVO more in my programming.
I have a view controller in my iPhone application which acts as the datasource and delegate for a UITableView. I also have a singleton model controller which coordinates populating my model with data fetched from the web.
In my view controller, I request that the model's controller load new data from the web. Then I can observe the "dataset" property of the singleton and receive KVO notifications when items are added to or removed from the set.
Now, each cell in my table view has an indicator which specifies whether the content in that cell has been read or not (like the blue "unread" dot in mail). Like mail, when a row is selected, I'll display details about that row. In the viewDidLoad for the detail view, I set the object's "read" property to YES. I would like the original view controller to be able to observe this "read" property of each object in the dataset, so that [tableView reloadData] can automatically be called as necessary and redraw the cells without the blue dot.
In researching this, I found the following link: http://homepage.mac.com/mmalc/CocoaExamples/controllers.html#observingACollection
According to this, it looks like I will do the following:
1) Be an observer of the array
2) Whenever I get a notification of a change to the array, I add (or remove) myself as an observer for the individual properties I am interested in.
3) When I get a notification of a change to the property I'm interested in, I can call [tableView reloadData]
I'm currently in the process of attempting to implement this approach. Can anyone with experience doing this offer some advice on this approach? If this the best way to handle this type of situation?
If this is the correct approach, would anyone be willing to share their implementation of adding/removing the observers for objects in the collection when the collection changes?
Thanks!

I think you can accomplish this task by using Core Data and the Fetched Results Controller.
I'm sure this can save you a lot of work.
Here's a good guide: Ray Wenderlich Core Data Tutorial, getting started

Related

How to update UITableView at run time, after the view is loaded

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.

Disable animation of UITableView with NSFetchedResultsController when many rows are being changed

In my UIView I've got a UITableView (UITV) which is controlled by an NSFetchedResultsController (NSFRC). The UIView is inside a UINavigationController.
When the view is about to be loaded/displayed I start some background activities which fetch data from a remote server (JSON) and parse into Core Data.
The NSFRC is being called when the parsing is done and the threaded NSManagedObjectContext have been merged into the main context.
The problem is that sometimes many rows are being inserted to Core Data at once, a lot of table cells are being added and there is quite a delay from that the actual fetching and parsing is done, until the rows are being displayed.
Now I wonder if anyone knows of any solution to, for example:
hook up a spinner to some "fetched results controller inserted all its rows for this time" (or something) notification/delegate call to at least tell the user that "something is going to show up soon"?
Or might the best solution simply be to not initialize the NSFRC until the background fetching and processing is completed?
Thanks!
If I understand your question correctly, you may want to look into the NSFetchedResultsControllerDelegate methods, with documentation available here: http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html
There are delegate methods available for pre changes with controllerWillChangeContent:, post changes with controllerDidChangeContent and during changes with didChangeSection: and didChangeObject.
I hope it helps!
Rog

iPhone MVC. Problems with the model

I'm new to programming, iphone application programming in specific. After reading a bunch about MVC I decided to give it a try in a small application. As to my understanding, MVC works like this:
Model: data, manipulating data, retrieving data.
ViewController: formats data from the model (NSDate to specific style), etc.
View: the actual gui.
If this is indeed a correct formulation of basic MVC theory, my confusion lies in how data is passed between the model, VC, and view. Example: if I make calls to twitter and get the data in the model, how do I (correctly) pass this information to the VC for further work. I know that between the VC and View one mostly uses IBOutlets. The Model is my real problem.
In my last app I made an NSString variable in the app delegate so I could access that data from any class. However, I read that this is not the best approach when the app becomes complex because the delegate is in charge of starting, ending the app, not holding data.
I've read of delegation methods, singleton's, NSNotification (which I've used to call methods in other classes). The problem is that I don't really understand how to use these techniques to pass data from the model to other views.
Please let me know if my question is unclear.
If you think about reusability, the main components that can be reused again are your model objects and view objects. They can be moved to different apps and still used properly. Your view controller is what is really specific to your app and where most of the app logic lies.
So in your example, you could have a twitter object that stores information and tweets from a user perhaps. You would create that class with all its functions separately within its own .h and .m file. Then in your view controller, instantiate the twitter class with data that is retrieved and begin using it from within the view controller.
Your view controller is actually retrieving the data but your model object is the one maintaining the data. In this way, you can pass on the model data with your twitter object to other view controllers.
Control over the application resides in the controller, so it is the object that will retrieve or save persisted data, update views with that data, and handle various events. Consider it the glue between the model and the view!
For example, if you were to click on a button to open a new modal view, you'd handle that event in your view controller. In the method that responds to the clicked button, you will create or access the new view controller and present it using presentModalViewController:animated:. If that new view and controller needs data that your current controller has access to, you could set a property in the new controller to refer to the object.

Objective C Callbacks and Notifications

I'm new to Objective-C and not a full time programmer. I'm beginning to understand the Model-View-Controller design pattern for differentiating the UI from the model. So the user takes an action and the view controller sends a message to the delegate (model). But I'm not sure what the best way to send actions from the delegate back to the view controller.
For example, the user pushes a button, the VC messages the Delegate. That part I understand. Then the delegate takes action, and following that the delegate wants to update the VC (e.g., update a label).
So what I missed (or have forgotten) is how this gets done, while maintaining separation between the UI and the model. I suppose I can use the notification center. Or I think I can just have the view controller pass a callback to the delegate. Or maybe there's another choice I don't know of. Can someone give me a recommendation, please?
I think you're slightly misunderstanding the MVC paradigm. Models should never be delegates of views, since models should have no dependencies or knowledge of any view classes. Typically, a view sends a message to its delegate or target (if you're using target/action), which is usually a controller (often a subclass of UIViewController on iOS). The controller then accesses data from the model and can update any views that need updating. I'd recommend reading the MVC fundamentals guide for a more complete explanation.
Basically you're right, you could do all the notification-related things yourself (i.e. with NotificationCenter) but since we're talking about UI-Stuff here I would greatly recommend you to use IBAction-Methods and IBOutlet-Properties in your code which you can easily connect to UI-Elements respectively their Callbacks in Interface Builder.
A very basic introduction to this topic can be found here:
iPhone SDK Interface Builder basic training
i hope that it is not too basic tough, and that I could lead you on the right track.
First of all delegate is NOT a Model.
Model is something passive that only holds the data (DB, plist, array, dictionary etc.).
While delegate is some set of functions that exist in order to react to some events.
Delegate is more likely to be a view controller in your case.
The view controller should react to user's action.
If the button tap should display some data from your model in some label then view controller should do all the work (receive user's action, take the necessary data from the model and display it on the view...).

How to observe managed object context

Whenever i make a change in the objects in the first tab of my application the updates are automatically upated in tab 2 becuase it uses a fetchedResultsController. Now i have a third tab that should also update itself, but how can i do that?
I only have a nsmangedObjectContext in the third tab to get the appropriate data. How can i receive notifications whenever the objects in this context change?
I am also struggeling with the question how i can make my data fetching more efficient, becuase tab 2 and 3 use the same set of data. I am currently making another fetch in tab 3, to get the same data as tab 2. I dont know how i can use the data from tab2 without disturbing the fetchedresultscontroller.
Information on this subject would really be appreciated!!
If your tableviews are very closely related, then you can just have a single UITableViewDataSource that provides data for both of them, and have it manage the NSFetchedResultsController. From your description, this case seems very likely.
If the tableviews are not very similar, such that having a single UITableViewDataSource would create excessive if() logic, then move your NSFetchedResultsController into an separate model object and post NSNotifications when it receives delegate call-backs. Your UITableViewDataSources can then observe those notifications to update themselves when they are on-screen.