Maintaining data sync between UITableView cells and array of model objects - iphone

I have a UITableView where each cell corresponds to a model object.The list of these model objects are kept in an array inside a singleton object that manages the model objects. The UITableViewController subclass holds a instance variable that references this singleton object. The model objects update their internal data asynchronously from the web. What's the best method for updating the table cells when the corresponding model object finishes reloading its data? Should the model objects send out a notification? Can the table cells use KVO to receive changes from the model objects? Is there another option? What is the best practice here?

I found a solution by subclassing UITableViewCell. Each cell maintains a reference to the model object that it corresponds to and observes a boolean isLoading property of this object. When the loading state changes, the cell updates it's data. In other words, the cell (view) object observes the model object, then requests data to present upon the model object state changing.

I'm not sure that is the best solution but in a previous project I was calling the message reloadRowsAtIndexPaths:
NSArray* paths = [[NSArray alloc] initWithObjects:indexPath, nil];
[tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationMiddle];

Related

Reload collection view with new data

How would I reload new data, say an array of names (strings), without re initializing the collection view with data?
I know of [uiCollectionView reloadData], but I wanted to changed the array of information associated with the collection view.
reloadData causes the collection view to ask its dataSource about what it now contains. Whatever the dataSource uses to decide, this is your collection view source data. If you change that data then you need to call reloadData for your UI to get updated. You can change the data however you want (like adding / removing items from the array or creating an entirely new array).
You never initialise the collection view with data. You initialise it with a delegate and dataSource. So you aren't re-initialising it. You're just changing the data that the dataSource is providing to the collection view.

How to write custom accessors for an NSManagedObject subclass?

I have a view called Cart. It displays a table of Items. These Items need to persist, so Item subclasses NSManagedObject; values like id, price, etc. are properties whose accessors are #dynamic so that they are automagically generated.
I have another view called Favorites. It displays a table of Items, but they don't need to persist. In fact, this view changes whenever the user logs in with different credentials.
The connection between the two views is that the user can add items to his cart from his favorites. A cart can store Items from different Favorites lists. Favorites lists don't change when the item is added to the cart.
Initially, I made the model for the Favorites view be an NSArray of NSDictionary objects. When the user adds the item to his cart, I create and save the item in Core Data from the NSDictionary key-value pairs. This approach doesn't look very clean or very DRY. Wouldn't it make more sense to make the Favorites view's model be an NSArray of Items?
So now my intent is to implement the Item class so that it will represent the Core Data model (NSManagedObject), but also work with the Favorites view. Being new to Objective-C and iOS development, I really don't know how this would work or look like. It seems that I would need to override the accessors that are magically created for me, but I can't call them at compile time using a super call... Can anyone give me a rough outline of when it would know to return the NSDictionary data or the Core Data data? In the case that it's Core Data data, how do I maintain the same level of efficiency that the magically-generated accessors would have?
Even better, is there a better implementation that is just as DRY or makes more sense? Or am I trying to combine too much functionality into one class? Is the NSArray of NSDictionary objects the best way to go in this case?
You can specify a result type on your fetch request (object, objectID, count, dictionary).
Also, I would not use NSManagedObjects outside of a MOC. You should either have a separate object that you use for memory stuff, or you can use an in-memory persistent store for those objects... or, you can just create a separate MOC as a child to your main database MOC that you use for your in-memory objects.
The advantage of these approaches is that your code does not have to know whether they are backed to the disk or not.
As long as you do not save the MOC, the changes to those objects will never go to disk.
EDIT
NSFetchRequest *fetchRequest = // create the fetch request...
fetchRequest.resultType = NSDictionaryResultType;
Now, when you make the fetch, instead of getting back an array of NSManagedObject you will get back an array of NSDictionary.

Referencing nsmutablearray to Data Model

I have a design issue which I am trying to analyze in my current project and thought maybe someone could help me figure this out. I have an nsarray object which I filter through predicate, and I want to set that object as my data model through view controller. First, is this a good practice of doing so? Since, I want to have an access of that object through out my transaction. I am not dealing with any database, plist, or core data model at current, these are just custom data model class I have created.
Thanks.
It's very common for a view of some sort to be backed by an NSArray, or an NSMutableArray. (Particularly, a UITableView, which can provide a single cell for each object in your array.)
Depending on the scope of your project, you can either investigate using Core Data for binding your model to your data:
CocoaDevCentral Core Data Overview
Or, for something a bit easier but less robust, you can look into implementing the methods defined in the UITableViewDelegate and UITableViewDataSource protocols, if you want to populate the cells of your table on a per-request basis.

Can I remove an object from the fetchedResultsController without deleting the object from the db?

I have been trying to remove an object from the tableView I am working with without deleting the object from the db, and I can't figure out how to do it.
I have tried setting a predicate on the fetchedResultsController, to filter objects that have a BOOL set to a certain value. Then, when I change that value, I expect that I can get that object to stay in the db, but out of the fetchedResultsController because of the predicate, but alas, that isn't working.
How can I remove an object from my tableView's dataSource (the fetchedResultsController) without deleting it from the core data db completely?
Please help! I've been bashing my head against this for way too long
I've always rolled my own table view data source when I need to weed out fetched results. NSFetchedResultsController objects are great when you want to show everything in your data base, but not so great when you want to weed out some of the data on the fly. I fetch the data, then iterate through the results array looking for the data I want to keep. The good objects get added to a new array, which becomes the basis of my table view data source.
The times I've implemented this, the data manipulation happens in a model object which hands off the array to the UITableViewController subclass that implements UITabelViewDataSource protocol methods. I suppose you could implement this as a subclass of NSFetchedResultsController, but I've never tried that approach.

What is the best practice to reference model objects in views with Core Data?

I have an NSManagedObject that described an animal, it has the attributes "name", "species", "scientificName" etc. I display all animals in a UITableView and managed the NSManagedObjects with an NSFetchedResultsController.
To provide my table view cells with the information necessary to render the content so far I just weakly referenced them to my NSManagedObject describing the animal. However, sometimes the NSManagedObject should get faulted and when the table view cells are redrawn, they re access the properties of the object and thus prevent the fault.
What are the best practices to provide view objects with information when using core data as data source? If possible I would like to avoid copying all attributes of the NSManagedObject over to the table view cell.
I believe it is a good practice to clearly separate the Model, View and Controller layers. Especially making sure the Views are not holding Model state. Holding on to a NSManagedObject holding on to a Model object. Copying some data is unavoidable.
I usually implement a method for "painting" the View with the Model data. Something like this in the UITableViewCell subclass:
-(void)configureWithAnimal:(NSManagedObject*)animal {
self.nameLabel.text = [animal valueForKey:#"name"];
self.speciesLabel.text = [animal valueForKey:#"species"];
// Etc.
}
This way it is a single line of code in the UITableViewController subclass to setup the cell, independently of newly created or reused cells. And if many tables wants to reuse the custom cell then not all f them need to reimplement the code to seeing up the cell.